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

stick-and-string

v1.1.0

Published

SAS 1.1 (Stick And String) — human-readable data serialization format. Parser, validator, and bidirectional JSON converter.

Readme

Stick And String (SAS 1.1)

A human-readable, deterministic data serialization format.

SAS is designed to be easy to read and write by hand, while remaining strict enough to parse unambiguously — no comma errors, no indentation-sensitivity, and full JSON interoperability.

# SAS 1.1 example
__sas_version__ -> "1.1"

server ::
    host -> "localhost"
    port -> 8080
    tags -> ["api" | "production"]
    tls  -> true
:: server

Install

Node.js / Browser

npm install stick-and-string

Python

pip install stick-and-string

Quick Start

JavaScript

import { parseSAS, sasToJSON, jsonToSAS } from 'stick-and-string';

// Parse SAS → JS object
const obj = parseSAS(`
server ::
    host -> "localhost"
    port -> 8080
:: server
`);
console.log(obj.server.port); // 8080

// SAS → JSON string
const json = sasToJSON(sasSource);

// JS object / JSON string → SAS
const sas = jsonToSAS({ host: 'localhost', port: 8080 });

CommonJS

const { parseSAS, sasToJSON, jsonToSAS } = require('stick-and-string');

Browser (ESM)

<script type="module">
  import { parseSAS } from './node_modules/stick-and-string/index.mjs';
</script>

Python

from sas_tools import parse_sas, sas_to_json, json_to_sas

# Parse SAS → dict
obj = parse_sas(open("config.sas").read())
print(obj["server"]["port"])  # 8080

# SAS → JSON string
json_str = sas_to_json(open("config.sas").read())

# dict → SAS string
sas = json_to_sas({"host": "localhost", "port": 8080})

CLI

Both packages install a sas command.

# Validate a SAS file
sas validate config.sas

# Convert SAS → JSON
sas to-json config.sas
sas to-json config.sas --output config.json
sas to-json config.sas --compact

# Convert JSON → SAS
sas to-sas data.json
sas to-sas data.json --output data.sas --no-version

# Round-trip check (great for CI)
sas roundtrip config.sas
sas roundtrip data.json

Format Overview

Key → Value pairs

name    -> "Alice"
port    -> 8080
enabled -> true
ratio   -> 3.14
nothing -> null

Block objects (named open/close)

server ::
    host -> "db.internal"
    port -> 5432
:: server

Inline objects (small, flat)

origin -> { lat -> 37.77 | lon -> -122.41 }

Inline arrays (scalars)

tags -> ["api" | "production" | "v2"]

Block arrays

hosts ::
    - "web1.internal"
    - "web2.internal"
:: hosts

Block arrays of objects

servers ::
    - ::
        host -> "a.local"
        port -> 8080
    :: -
    - ::
        host -> "b.local"
        port -> 9090
    :: -
:: servers

Multiline strings

description -> """
Line one.
Line two.
"""

Comments

# This is a comment
# Inline comments are NOT permitted

API Reference

JavaScript

| Export | Signature | Description | |--------|-----------|-------------| | parseSAS | (source: string) → object | Parse SAS document | | sasToJSON | (source, {indent, stripVersion}) → string | SAS → JSON string | | sasToObject | (source) → object | SAS → plain JS object | | jsonToSAS | (input, {versionHeader, indent}) → string | object/JSON → SAS | | SASParseError | class | Parse error with .lineNum | | JSONToSASError | class | Serialization error with .path |

Python

| Export | Signature | Description | |--------|-----------|-------------| | parse_sas | (source: str) → dict | Parse SAS document | | sas_to_json | (source, indent, strip_version) → str | SAS → JSON string | | sas_to_object | (source) → dict | SAS → Python dict | | json_to_sas | (input, version_header, indent) → str | dict/JSON → SAS | | SASParseError | class | Parse error with .line_num | | JSONToSASError | class | Serialization error with .path |


Error Codes

All errors include a line number. Parser errors are never silent.

| Code | Description | |------|-------------| | E01 | Duplicate key in same scope | | E02 | Block closer mismatch or bare :: | | E03 | Unclosed block or multiline string at EOF | | E04 | Invalid escape sequence | | E05 | Invalid number (leading zero, +, NaN, etc.) | | E06 | Wrong-case boolean or null (True, NULL, …) | | E07 | Inline comment | | E08 | Missing spaces around -> | | E09 | Missing spaces around \| in inline array/object | | E10 | Trailing \| | | E11 | Non-scalar in inline array | | E12 | Nested inline object | | E13 | Key starting with - | | E14 | Mixed block content (array items + pairs) | | E15 | Anonymous closer outside array context |


Publishing

npm

cd npm/
npm publish --access public

PyPI

cd pip/
pip install build twine
python -m build
twine upload dist/*

License

Copyright (c) 2025 Sourasish Das
Licensed under the Vexon Open-Control License (VOCL) 1.0.