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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@webreflection/magic-view

v0.2.15

Published

DataView with automatically grown buffer

Downloads

102

Readme

MagicView

Coverage Status

Social Media Photo by Simon Berger on Unsplash

A DataView like utility that automatically grows while adding data to its underlying buffer.

import { MagicView, BetterView } from 'https://esm.run/@webreflection/magic-view';
// BetterView is a DataView with get/setTyped and get/setArray methods on top

// types
type Init = number | number[] | ArrayBuffer | ArrayBufferView;

class MagicView extends DataView {
    // meta-description of the constructor per `init` type
    constructor(init:Init?, byteOffset = 0) {
        if (typeof init === 'number')       // 0xFFFF
            this.#buffer = new ArrayBuffer(init);
        else if (Array.isArray(init))       // [1, 2, 3, 4]
            this.#buffer = new Uint8Array(init).buffer;
        else if (ArrayBuffer.isView(init))  // Uint8Array or others
            this.#buffer = init.buffer;
        else if (init)                      // ArrayBuffer
            this.#buffer = init;
        else
            this.#buffer = new ArrayBuffer(0xFFFF);

        // internally the buffer is handled via optional byteOffset
        this.#view = new Uint8Array(this.#buffer, byteOffset);
    }

    // returns the current Uint8Array view length which
    // might change in the future
    get byteLength() {}

    // when accessed, it seals the deal, meaning all operations
    // after will likely fail due detached buffer. This is meant
    // to be accessed only after all operations are done
    get buffer() {}

    // returns the current size of the written bytes which
    // will be the equivalent of the returned buffer byteLength
    get size() {}

    // finalize operations, create a Uint8Array of the internal buffer
    // and automatically reset the state for this reference, allowing
    // further operations from scratch next time it's needed
    get view() {}

    // reads bytes from byteOffset to byteOffset + size and return
    // a typed array - by default it's a Uint8Array, example:
    // getTyped(pos, Float64Array.BYTES_PER_ELEMENT, Float64Array):Float64Array
    // returns a Float64Array with length 1 and the number at its index 0
    getTyped(byteOffset:number, size:number, Class:TypedArray = Uint8Array) {
        return new Class(size);
    }

    // like any other DataView method except it accepts
    // any TypedArray and it adds that to the underlying buffer
    // on matter the length of it: it will grow if needed
    setTyped(byteOffset:number, typed:TypedArray) {}

    // after all operations are done and the `buffer`
    // has been retrieved, reuse this same instance
    // for better JIT performance, where possible
    reset() {}
}

What problem does this module solve?

The DataView primitive is pretty awesome but it's decoupled with the handling of the buffer in term of size, even if the byteOffset is mandatory and it should be tracked elsewhere while building up the final buffer.

Here, things are simpler:

// add sequentially 3 Int32 values
mv.setInt32(mv.size, 123);
mv.setInt32(mv.size, 456);
mv.setInt32(mv.size, 789);
// add an encoded string too
mv.setTyped(mv.size, new TextEncoder().encode("magic"));

As the size of each numeric type is known it made somehow sense to me to have a thin indirection able to keep "growing" the buffer, without using a resizable ArrayBuffer at all, simply transfering buffers each time size boundaries are touched.

This utility avoids headaches around how much big should be the maxByteLength for a resizable ArrayBuffer, working as fast as a resizable SharedArrayBuffer would work but it tries to keep the amount of needed/used RAM minimal, with a default set to 0xFFFF (64K of RAM) which is also the size it increments the buffer each time that limit is reached.

Such size is retrieved / inferred when an explicit initial size or ArrayBuffer with a specific size has been defined, so that it could start from more than 64K or even less, if your encoding/decoding is going to be narrowed somehow.

As summary, this module is ideal to encode incrementally while a DataView would be ideal to decode as its performance would be unmatched, yet this module could be used to decode too with 2X slowdown due extra operations needed to populate each right number via the right data.