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

@0xintuition/atom-parser

v0.1.0-alpha.0

Published

Detect and normalize atom inputs, with optional remote content inspection

Readme

@0xintuition/atom-parser

Classifies and normalizes arbitrary string inputs into structured types. Detects IPFS URIs, Ethereum addresses, ENS names, JSON, URLs, ISBNs, and plain strings. Remote content inspection is enabled by default for URLs and IPFS URIs.

Installation

bun add @0xintuition/[email protected]

The package ships compiled ESM and TypeScript declarations. It uses standard Fetch and Web Streams APIs for remote inspection; Node.js 22+ and Bun are supported. Local detection can run without network access by passing { remoteFetch: false }.

Quick Start

import { parseAtom } from '@0xintuition/atom-parser'

const result = await parseAtom('vitalik.eth')
// {
//   input: 'vitalik.eth',
//   normalizedInput: 'vitalik.eth',
//   kind: 'ens_name',
//   name: 'vitalik.eth',
//   warnings: []
// }

All kind-specific fields are at the top level — no nesting required.

Imports

The root entry point exports the parser, local detection, remote inspection, and shared types. Existing subpath imports are also supported:

import { parseAtom } from '@0xintuition/atom-parser/parse'        // Main entry point
import { detectLocal } from '@0xintuition/atom-parser/detect'      // Local detection only
import { inspectRemote } from '@0xintuition/atom-parser/remote'    // Remote inspection
import type { ParseResult, ParseOptions } from '@0xintuition/atom-parser/types'

Detected Kinds

Inputs are classified in the following priority order:

| Kind | Example Input | Description | | ------------------- | ------------------------------------------ | -------------------------------------------- | | ipfs | ipfs://bafybei... | IPFS URIs (ipfs:// or /ipfs/) with valid CID | | ethereum_address | 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 | 42-character hex address | | ens_name | vitalik.eth | ENS domain names ending in .eth | | json | {"key":"value"} | Valid JSON objects or arrays | | url | https://example.com | HTTP(S) URLs | | isbn | 978-0-306-40615-7 | ISBN-10 or ISBN-13 with valid checksum | | plain_string | hello world | Anything that doesn't match above |

Examples

Ethereum Address

const result = await parseAtom('0xd8da6bf26964af9d7eed9e03e53415d37aa96045')
// {
//   input: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
//   normalizedInput: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
//   kind: 'ethereum_address',
//   address: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
//   checksumAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
//   warnings: []
// }

IPFS URI

const result = await parseAtom(
  'ipfs://bafybeigdyrzt5rj6uqb6t5x3r7b6g6j4gh7f6wzsp4r4i2l3x6jt6s5z3e/metadata/item.json',
  { ipfsGatewayBaseUrl: 'https://ipfs.io/' }
)
// {
//   kind: 'ipfs',
//   subtype: 'json_document',           // from remote inspection (on by default)
//   cid: 'bafybeigdyrzt5rj6uqb6t5x3r7b6g6j4gh7f6wzsp4r4i2l3x6jt6s5z3e',
//   canonicalUri: 'ipfs://bafybeigdyrzt5rj6uqb6t5x3r7b6g6j4gh7f6wzsp4r4i2l3x6jt6s5z3e/metadata/item.json',
//   path: 'metadata/item.json',
//   gatewayUrl: 'https://ipfs.io/ipfs/bafybeigdyrzt5rj6uqb6t5x3r7b6g6j4gh7f6wzsp4r4i2l3x6jt6s5z3e/metadata/item.json',
//   remote: { outcome: 'success', subtype: 'json_document', ... },
//   ...
// }

Without a gateway configured, gatewayUrl is undefined and remote inspection is skipped:

const result = await parseAtom('ipfs://bafybeigdyrzt5rj6uqb6t5x3r7b6g6j4gh7f6wzsp4r4i2l3x6jt6s5z3e')
// result.gatewayUrl === undefined
// result.remote?.outcome === 'skipped'

URL with Remote Inspection

Remote inspection is on by default. The subtype is promoted to the top level:

const result = await parseAtom('https://example.com')
// {
//   kind: 'url',
//   subtype: 'webpage',                 // immediately visible
//   canonicalUrl: 'https://example.com/',
//   scheme: 'https',
//   host: 'example.com',
//   path: '/',
//   hasQuery: false,
//   remote: { outcome: 'success', statusCode: 200, contentType: 'text/html', ... },
//   warnings: []
// }

To skip remote inspection:

const result = await parseAtom('https://example.com', { remoteFetch: false })
// result.subtype === undefined
// result.remote === undefined

JSON

const result = await parseAtom('{"url":"https://example.com"}')
// {
//   kind: 'json',
//   topLevelType: 'object',
//   objectKeyCount: 1,
//   arrayLength: undefined,
//   ...
// }

const arr = await parseAtom('["https://example.com",42]')
// {
//   kind: 'json',
//   topLevelType: 'array',
//   objectKeyCount: undefined,
//   arrayLength: 2,
//   ...
// }

JSON scalars ("string", 123, true, null) are not detected as JSON — they fall through to plain_string.

ISBN

const result = await parseAtom('978-0-306-40615-7')
// {
//   kind: 'isbn',
//   canonical: '9780306406157',
//   format: 'isbn13',
//   checksumValid: true,
//   ...
// }

const isbn10 = await parseAtom('155860832X')
// {
//   kind: 'isbn',
//   canonical: '155860832X',
//   format: 'isbn10',
//   checksumValid: true,
//   ...
// }

Plain String

Any input that doesn't match the above kinds falls back to plain_string:

const result = await parseAtom('  hello world  ')
// {
//   kind: 'plain_string',
//   original: '  hello world  ',
//   trimmed: 'hello world',
//   ...
// }

Result Structure

ParseResult is a discriminated union on kind. TypeScript narrows the type automatically:

const result = await parseAtom(input)

if (result.kind === 'url') {
  result.subtype    // RemoteContentKind | undefined
  result.scheme     // string
  result.host       // string | undefined
}

if (result.kind === 'ipfs') {
  result.subtype    // RemoteContentKind | undefined
  result.cid        // string
  result.gatewayUrl // string | undefined
}

if (result.kind === 'ethereum_address') {
  result.checksumAddress // string
}

Only url and ipfs results have subtype and remote fields. Other kinds don't have remote inspection.

Remote Content Subtypes

| Subtype | Detected By | | ----------------- | ------------------------------------------------- | | webpage | text/html content type or HTML in body | | json_document | application/json content type or valid JSON body | | image | image/* content type or PNG/JPEG/GIF magic bytes | | video | video/* content type or MP4 magic bytes | | audio | audio/* content type or RIFF/ID3 magic bytes | | generic_file | Known content type but not one of the above | | unknown_remote | Empty body, no content type clues |

Remote Outcomes

| Outcome | Meaning | | -------------------------- | ---------------------------------------------------- | | success | Fetched and classified successfully | | skipped | Skipped (e.g., no IPFS gateway configured) | | denied | Blocked by security policy (private network, scheme) | | timeout | Request timed out | | error | Network or fetch error | | oversized | Response exceeded the byte limit | | redirect_limit_exceeded | Too many redirects |

Options

interface ParseOptions {
  remoteFetch?: boolean            // Enable remote inspection (default: true)
  maxInputBytes?: number           // Max UTF-8 input size in bytes (default: 16,384)
  ipfsGatewayBaseUrl?: string      // IPFS gateway base URL for gateway URL construction
  allowHttp?: boolean              // Allow HTTP (not just HTTPS) for remote fetch (default: false)
  allowPrivateNetworks?: boolean   // Allow fetching private/localhost IPs (default: false)
  maxRedirects?: number            // Max redirects to follow (default: 3)
  connectTimeoutMs?: number        // Reserved; Fetch does not expose a separate connection timeout
  requestTimeoutMs?: number        // Timeout per request, including body reads (default: 5,000)
  ipfsRequestTimeoutMs?: number    // IPFS-specific timeout (default: 8,000)
  maxResponseBytes?: number        // Max response body size (default: 1,048,576)
  inspectBytes?: number            // Bytes to read for content sniffing (default: 262,144)
}

Remote transport policy

The parser checks the URL scheme and literal hostname before every request, including redirects. With allowPrivateNetworks: false, it rejects localhost and private IPv4/IPv6 literals, including private IPv4 addresses embedded in IPv6. The request timeout covers headers and body consumption for each redirect hop.

These checks do not resolve DNS, pin destination addresses, or prevent DNS rebinding. Services accepting untrusted URLs must enforce destination restrictions at their egress proxy, firewall, or transport layer. Keep those deployment controls in the application; the parser uses the runtime's global fetch. The connectTimeoutMs field remains available for compatibility but is not independently enforced; requestTimeoutMs bounds the complete fetch instead.

Error Handling

parseAtom throws ParseError for invalid inputs:

import { ParseError } from '@0xintuition/atom-parser/types'

try {
  await parseAtom('')
} catch (err) {
  if (err instanceof ParseError) {
    console.log(err.code)    // 'EMPTY_INPUT'
    console.log(err.message) // 'input must not be empty'
  }
}

| Error Code | Cause | | ----------------------- | ---------------------------------- | | EMPTY_INPUT | Input is empty or whitespace-only | | INPUT_TOO_LARGE | Input exceeds maxInputBytes | | INVALID_IPFS_GATEWAY | Malformed IPFS gateway URL | | INVALID_REQUEST | Invalid request parameters | | INTERNAL_ERROR | Unexpected internal failure |

Detection Precedence

When an input could match multiple kinds, the first match wins:

  1. IPFS (ipfs:// or /ipfs/ prefix)
  2. Ethereum address (0x + 40 hex chars)
  3. ENS name (*.eth)
  4. JSON (valid object or array)
  5. URL (HTTP(S) URL)
  6. ISBN (valid ISBN-10 or ISBN-13)
  7. Plain string (fallback)