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

@pie-qti/ims-cp-node

v0.1.0

Published

Node.js-specific IMS Content Package utilities for server-side QTI processing

Readme

@pie-qti/ims-cp-node

Node.js-specific IMS Content Package utilities for server-side QTI processing.

Features

  • ZIP Extraction: Secure ZIP/IMSCC package extraction with path traversal protection
  • Manifest Resolution: Parse and resolve IMS manifest files using @pie-qti/ims-cp-core
  • Directory Support: Work with both extracted directories and ZIP files
  • Temporary Extraction: Automatic temp directory management with cleanup
  • Localized Resources: Built-in support for multilingual content packages
  • Type-Safe API: Full TypeScript support with comprehensive type definitions

Installation

bun add @pie-qti/ims-cp-node

Usage

Opening Packages

import { openContentPackage, loadResolvedManifest } from '@pie-qti/ims-cp-node';

// Open a ZIP file (extracts to temp directory)
const pkg = await openContentPackage('/path/to/package.zip');
console.log(`Package root: ${pkg.packageRoot}`);

// Load and parse manifest
const manifest = await loadResolvedManifest(pkg.packageRoot);
console.log(`Items: ${manifest.items.length}`);

// Clean up temp directory
await pkg.close();

Working with Directories

// Open an already-extracted package directory
const pkg = await openContentPackage('/path/to/extracted-package');
const manifest = await loadResolvedManifest(pkg.packageRoot);

// No cleanup needed for directory packages
await pkg.close(); // no-op

Extracting to Specific Directory

// Extract to a specific location (no temp cleanup)
const pkg = await openContentPackage('/path/to/package.zip', {
  extractToDir: '/path/to/extract-location'
});

Accessing Manifest Resources

const manifest = await loadResolvedManifest(packageRoot);

// Access QTI items
for (const item of manifest.items) {
  console.log(`Item: ${item.identifier}`);
  console.log(`Main file: ${item.hrefResolved}`);
  console.log(`Dependencies: ${item.filesResolved.join(', ')}`);
}

// Get absolute file path for reading
import { toAbsolutePath } from '@pie-qti/ims-cp-node';
const itemPath = toAbsolutePath(packageRoot, item.hrefResolved);
const itemXml = await readFile(itemPath, 'utf-8');

Localized Packages

import { loadLocalizedResolvedManifest } from '@pie-qti/ims-cp-node';

// Load with locale support
const manifest = await loadLocalizedResolvedManifest(packageRoot, 'en-US');

console.log('Available locales:', manifest.localized.availableLocales);

// Access localized item variants
const item = getLocalizedItem(manifest.localized, 'item-id', 'es-ES');

API

openContentPackage(inputPath, options?)

Opens a content package from a ZIP file or directory.

Parameters:

  • inputPath: string - Path to ZIP file or directory
  • options?: OpenContentPackageOptions
    • tmpRootDir?: string - Custom temp directory location
    • extractToDir?: string - Extract to specific directory (disables temp cleanup)

Returns: Promise<OpenContentPackage>

  • packageRoot: string - Absolute path to package root
  • isTemporary: boolean - Whether package was extracted to temp
  • close: () => Promise<void> - Cleanup function (removes temp dir)

loadResolvedManifest(packageRoot)

Parses and resolves manifest with all resource paths.

Parameters:

  • packageRoot: string - Absolute path to package root

Returns: Promise<ResolvedManifest>

  • identifier: string - Package identifier
  • manifestPath: string - Relative path to manifest file
  • resources: Map<string, ResolvedManifestResource> - All resources by ID
  • items: ResolvedManifestResource[] - QTI assessment items
  • passages: ResolvedManifestResource[] - QTI passages
  • tests: ResolvedManifestResource[] - QTI tests

loadLocalizedResolvedManifest(packageRoot, defaultLocale?)

Loads manifest with localized resource grouping.

Parameters:

  • packageRoot: string - Absolute path to package root
  • defaultLocale?: string - Default locale (default: "en-US")

Returns: Promise<LocalizedResolvedManifest> - Extends ResolvedManifest with localized property

toAbsolutePath(packageRoot, packageRelativePosixPath)

Converts package-relative POSIX path to absolute filesystem path.

Parameters:

  • packageRoot: string - Package root directory
  • packageRelativePosixPath: string - Package-relative path

Returns: string - Absolute filesystem path

extractZipToDir(zipPath, targetDir)

Extracts a ZIP file to a directory with security checks.

Parameters:

  • zipPath: string - Path to ZIP file
  • targetDir: string - Target extraction directory

Returns: Promise<void>

Security

This package includes protection against ZIP path traversal attacks:

  • Validates all entry paths
  • Rejects paths with .. segments
  • Rejects absolute paths
  • Ensures all extracted files stay within target directory

Dependencies

  • unzipper - Secure ZIP extraction for Node.js
  • @pie-qti/ims-cp-core - Universal manifest parsing utilities

License

MIT