Glorious Binary Serialization and Deserialization for TypeScript.

Overview

Sir Dez

Glorious SerDes for TypeScript

The library you can rely on,
For binary serialization and deserialization,
In Node, Deno, and the Web environment,
Which is simple and yet performant.

npm deno ci coverage report docs perf bundle

Features

  • Performant
  • Easy to use
  • Full TypeScript support
  • Super extensible
  • 99% tree-shakable
  • Zero dependencies (small footprint)
  • Runs in Node, Deno and browsers
  • More details...

Performance Comparison with other tools in Node (ops/sec)

performance

Installation

Expand for more details.

Node (with or without bundlers)

In the terminal with NPM

npm i sirdez

Or with Yarn

yarn add sirdez

In the code with ES Modules

import * as sd from "sirdez";

or with CommonJS

const sd = require("sirdez");
Web (without bundlers)

In HTML with UMD

<script src="https://cdn.jsdelivr.net/npm/sirdez/dist/sirdez.umd.js"></script>

In an ES module script (statically)

import * as sd from "https://cdn.jsdelivr.net/npm/sirdez/dist/sirdez.es.js";

In an ES module script (dynamically)

const sd = await import(
  "https://cdn.jsdelivr.net/npm/sirdez/dist/sirdez.es.js"
);
Deno

In code (statically)

import * as sd from "https://deno.land/x/sirdez/mod.ts";

In code (dynamically)

const sd = await import("https://deno.land/x/sirdez/mod.ts");

Usage

Creating a simple SerDes.

const person = sd.use(
  sd.struct({
    name: sd.string(sd.utf8, sd.uint8),
    age: sd.uint8
  })
);

const bytes = person.toBytes({
  name: "Bob",
  age: 23
});

const samePerson = person.fromBytes(bytes);

console.log({ bytes, samePerson });

Using TypeScript utilities

type Person = sd.GetType<typeof person>;

const bob: Person = {
  name: "Bob",
  age: 23
};

Resources

Contribution

Help and suggestions are welcomed!

Comments
  • Calling 'fromBytes' after calling 'toBytes' returns tainted data

    Calling 'fromBytes' after calling 'toBytes' returns tainted data

    I'm trying to understand a strange behavior I observed. I ran into this when I started seeing ghost data show up in my application.

    It would seem to me that calling toBytes with an empty Uint8Array should always return the same result no matter what previously happened with fromBytes.

    Here's a sample.

    import * as sd from "sirdez"
    
    const test = sd.use(
      sd.struct({
        foo: sd.string(sd.utf8js, sd.uint8),
      })
    )
    
    const objOne = test.fromBytes(new Uint8Array())
    console.log(objOne) // -> { foo: '' }
    
    // this taints future calls to fromBytes()
    const arrOne = test.toBytes({ foo: "bar" })
    console.log(arrOne)
    
    // Why is this returning { foo: 'bar' } and not { foo: '' }
    // It seems that the call to toBytes leaves some state hanging around?
    const objTwo = test.fromBytes(new Uint8Array())
    console.log(objTwo) // -> { foo: 'bar' } 
    
    opened by grempe 15
  • [RangeError] `use` missing size parameter

    [RangeError] `use` missing size parameter

    Using this serde declaration:

    sd.use(sd.array(sd.bytes(sd.uint32), sd.uint32));
    

    I get the following error:

    RangeError: offset is out of bounds
        at Uint8Array.set (<anonymous>)
        at Object.ser (.../node_modules/sirdez/src/serdes/bytes.ts:9:17)
        at .../node_modules/sirdez/src/serdes/array.ts:10:12
        at contextSer (.../node_modules/sirdez/src/context.ts:27:7)
        at Object.toBytes (.../node_modules/sirdez/src/use.ts:14:34)
        at serialize (.../src/datasources/srs.ts:391:42)
        at CacheClient.set (.../src/lib/redis-cache/cache.js:203:48)
        at CacheClient.tryGet (.../src/lib/redis-cache/cache.js:131:24)
    

    Looking at the source code I should be able to create a context with a larger size than the default value. For that I would expect to call use second parameter, size with a size.

    However, the signature available for sd.use in my current project is this:

    function use<T>(
      { ser, des }: Serdes<T>
    ): UsableSerdes<T>
    

    I was expecting to have something like this:

    function use<T>(
      { ser, des }: Serdes<T>,
      size?: number
    ): UsableSerdes<T>
    
    • package version: 0.0.6

    What am I doing wrong?

    opened by goliatone 6
  • Folder structure to prevent export bugs

    Folder structure to prevent export bugs

    I've noticed that usize is not exported in noeval.ts, even though usize doesn't use eval. I guess it's a bug, because in noeval.ts you had to export every serdes other than struct and number manually, and it's easy to forget to export something.

    What about using such folder structure so it's harder to miss something:

    • shared_serdes contains serdeses which can be used both in eval and noeval
    • serdes contains serdeses which use eval
    • noeval_serdes contains versions of serdeses from serdes, but without eval usage

    There are 4 index files for every combination Node.js/not Node.js and eval/noeval. shared.ts contains common exports

    opened by azerum 2
  • Improve documentation for `noeval`.

    Improve documentation for `noeval`.

    I ran into a problem with sirdez when trying to run it in the context of a Cloudflare Worker.

    Workers (and probably most serverless environments) do not allow eval or new Function calls.

    https://github.com/cloudflare/wrangler/issues/1268

    Once I narrowed the problem down to sirdez (which I could only see in the worker dev environment, not from production logs) I was pleased to see there was a noeval option.

    It took some digging around and experimentation though to figure out how to actually use it.

    Having a section of the README dedicated to this would be helpful. Or bring it more up front in the docs.

    Note also that Socket.dev calls out sirdez with a warning since it uses new Function.

    https://socket.dev/npm/package/sirdez/overview/0.0.6

    You might think about having the default be to use the noeval version and let people opt-in to the more unsafe behavior.

    You mentioned in the docs that there is a performance hit when using noeval structs.

    https://weisrc.github.io/sirdez/data_types/struct.html#variants

    much slower because it is implemented using a for loop

    I tried to follow the link on the README to Performance Results to better understand the impact but its a broken link.

    https://github.com/weisrc/sirdez/blob/main/TODO

    opened by grempe 2
  • Use no-eval by default

    Use no-eval by default

    Updated code, tests, build configs and docs. Will need to change the major version, as it is a breaking change

    Not sure why these files should be ignored by eslint. Do I need to change noeval.ts to eval.ts?

    opened by azerum 1
  • move oneOf types to src/types, add docs

    move oneOf types to src/types, add docs

    I've simplified code, moved some types to src/types, so typedoc will generate documentation for it, and added docs page for sd.oneOf with hopefully clear explanation

    P.S. I think #7 checks failed because I had accidentally used npm i instead of yarn

    opened by azerum 1
  • add oneOf

    add oneOf

    My try on generic function for use case #6

    For the following structure:

    const OneOf = sd.oneOf({
      a: sd.uint8,
      b: sd.array(sd.uint8, sd.uint8)
    });
    

    It will create Serdes<T> where T is:

    type OneOf = {
      type: 'a';
      value: number;
    } | { 
      type: 'b';
      value: number[];
    }   
    

    P.S. Thank you for such an elegant and nice to use library

    opened by azerum 1
  • Question: differentiating between different types

    Question: differentiating between different types

    Is there a recommended approach to differentiating different structs?

    Currently I define a type as the first prop in every struct. And then check the first value in the encoded bytes. So far it works fine, but I don't know if it's a good idea.

    const Foo = sd.use(
        sd.struct({
            type: sd.uint8,
            foo: sd.uint8,
            // ...
        }),
    );
    
    const Bar = sd.use(
        sd.struct({
            type: sd.uint8,
            bar: sd.uint8,
            // ...
        }),
    );
    
    // ...
    
    switch (bytes[0]) {
        case Type.Bar:
            const bar = Bar.fromBytes(bytes);
            break;
    
        case Type.Foo:
            const foo = Foo.fromBytes(bytes);
            break;
    
        default:
            break;
    }
    
    

    p.s: thank you for this library, took me forever to find it, but i'm so glad I did

    opened by pecnik 1
Releases(0.0.6)
Owner
Wei
Nothing special about me...
Wei
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
A RESP 'Redis Serialization Protocol' library implementation to generate a server, uses a similar approach to express to define you serer, making it easy and fast.

RESPRESS A RESP 'Redis Serialization Protocol' library implementation to generate a server, uses a similar approach to express to define you serer, ma

Yousef Wadi 9 Aug 29, 2022
Serialize arbitrary NodeJS closures and customize serialization behavior.

Closure Serializer This is a fork of the Pulumi Closure Serializer. @pulumi/pulumi. Motivation Functionless allows developers to write cloud applicati

null 4 Jul 19, 2022
Serialization library for data-oriented design structures in JavaScript

Data-oriented Serialization for SoA/AoA A zero-dependency serialization library for data-oriented design structures like SoA (Structure of Arrays) and

null 11 Sep 27, 2022
superserial provides serialization in any way you can imagine.

superserial After data transfer, when the object needs to be restored, JSON has many limitations. It does not support values such as Infinity and NaN,

DenoStack 24 Dec 23, 2022
⛑️ JSON serialization should never fail

⛑️ JSON serialization should never fail. Features Prevent JSON.serialize() from: Throwing Changing types Filtering or transforming values unexpectedly

ehmicky 191 Dec 15, 2022
ltp is a parseless copyfree binary encoding format

ltp is a parseless copyfree binary encoding format. This means that you can read a field out of ltp encoded data without

Socket Supply Co. 27 Aug 10, 2022
shell script replacement; write shell scripts in js instead of bash, then run them with a single static binary

yavascript YavaScript is a bash-like script runner which is distributed as a single statically-linked binary. Scripts are written in JavaScript. There

Lily Scott 59 Dec 29, 2022
Library to download binary files from GitHub releases detecting the correct platform.

Dbin TypeScript library to download binary files from GitHub releases detecting the correct platform. Example: import dbin from "https://deno.land/x/d

Óscar Otero 7 Oct 4, 2022
:books: The definitive guide to TypeScript and possibly the best TypeScript book :book:. Free and Open Source 🌹

TypeScript Deep Dive I've been looking at the issues that turn up commonly when people start using TypeScript. This is based on the lessons from Stack

Basarat Ali Syed 18.7k Jan 4, 2023
This project is a boilerplate for Next and TypeScript projects. This template was built with Vite, TypeScript and Stitches.

Awesome Template Stitches — NextJS, TypeScript, Stitches and Design Tokens Summary About this template Avaliale scripts Other scripts available Main t

Diego Silva 14 Dec 29, 2022
Movehat is a TypeScript SDK for Move on Sui built on top of Sui's TypeScript SDK and our fork of Ian Macalinao's `move-ts`.

Movehat Movehat is a TypeScript SDK for Move on Sui built on top of Sui's TypeScript SDK and our fork of Ian Macalinao's move-ts. Movehat aspires to b

Pentagon 10 Sep 30, 2022
A CLI tool to create a NodeJS project with TypeScript CTSP is a CLI tool to make easier to start a new NodeJS project and configure Typescript on it.

CTSP- Create TS Project A CLI tool to create a NodeJS project with TypeScript CTSP is a CLI tool to make easier to start a new NodeJS project and conf

Jean Rodríguez 7 Sep 13, 2022
Variant types in Roblox TypeScript - Ported from Vanilla TypeScript

Variant (for Roblox) This is a roblox typescript variant (heh, pun) of Variant. See the Variant documentation on how to use Variant. A variant type is

Australis 2 Jun 3, 2022
A Lua plugin, written in TypeScript, to write TypeScript (Lua optional).

typescript.nvim A minimal typescript-language-server integration plugin to set up the language server via nvim-lspconfig and add commands for convenie

Jose Alvarez 315 Dec 29, 2022
typescript-to-jsonschema generates JSON Schema files from your Typescript sources.

fast-typescript-to-jsonschema English | 简体中文 a tool generate json schema from typescript. Feature compile Typescript to get all type information conve

yunfly 21 Nov 28, 2022
Convert some JavaScript/TypeScript code string into a .d.ts TypeScript Declaration code string

convert-to-dts Converts the source code for any .js or .ts file into the equivalent .d.ts code TypeScript would generate. Usage import { convertToDecl

Lily Scott 11 Mar 3, 2022