Skip to content

nokia/ts-serialize-closures

Repository files navigation

License npm version npm version Build Status

ts-serialize-closures

Serialize your TypeScript functions!

ts-serialize-closures can serialize and deserialize arbitrary TypeScript/JavaScript object graphs. That includes:

  • functions, which may have captured data,
  • Date and RegExp objects,
  • cyclic graphs,
  • prototypes,
  • references to built-in objects,
  • etc.

The idea is that serialize creates a self-contained snapshot of all program state relevant to the object being serialized. The deserialize function decodes that snapshot back to a JavaScript object graph.

This tool might be useful in a number of scenarios:

  • Exchanging functions between different processes. That's often a useful tool for building distributed systems.

  • Lightweight remote post-mortem debugging: have failing processes create a neat little snapshot of their current state and send yourself that snapshot for analysis.

Usage

The serializer (serialize-closures) requires a preprocessing step (ts-closure-transform). Therefore, the typical usage of this library is to configure webpack to automatically transform the source code using a hook in the TypeScript compiler (tsc). Take the following steps to set up a stand-alone example:

  1. Prepare project and install dev-dependencies
mkdir example && cd example
npm init
npm install --save-dev ts-closure-transform serialize-closures webpack webpack-cli typescript ts-loader util

2.1 Configure tsconfig.json:

{
    "compileOnSave": true,
    "compilerOptions": {
        "target": "ES5",
        "module": "commonjs",
        "declaration": true,
        "moduleResolution": "node",
        "stripInternal": true,
        "jsx": "react",
        "outDir": "dist"
    },
    "include": [
        "src/**/*"
    ],
    "exclude": [
        "node_modules",
        "dist"
    ]
}

2.2 Configure webpack.config.js:

const tsClosureTransform = require('ts-closure-transform');
const path = require('path');
module.exports = {
  entry: {
    example: './src/example.ts',
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /.tsx?$/,
        loader: 'ts-loader', // or 'awesome-typescript-loader'
        options: {
          getCustomTransformers: () => ({
            before: [tsClosureTransform.beforeTransform()],
            after: [tsClosureTransform.afterTransform()]
          })
        }
      }
    ]
  },
  resolve: {
    extensions: [ '.tsx', '.ts', '.js' ],
    fallback: {
      "util": require.resolve("util/"),
    },
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].bundle.js',
  }
}
  1. Write code src/example.ts to serialize and deserialize arbitrary functions:
import { serialize, deserialize } from 'serialize-closures';
// Just about anything can be serialized by calling `serialize`.
let capturedVariable = 5;
let serialized = serialize(() => capturedVariable);

// Serialized representations can be stringified and parsed.
let text = JSON.stringify(serialized);
let parsed = JSON.parse(text);

// Serialized representations can be deserialized by calling `deserialize`.
console.log(deserialize(serialized)()); // Prints '5'.
console.log(deserialize(parsed)());     // Prints '5'.
  1. Compile with webpack and run the sample
npx webpack
node dist/example.bundle.js

Components

The serializer consists of two components.

  1. ts-closure-transform: a transformation to inject in the TypeScript compiler's pass pipeline. This transformation will rewrite all function definitions to include a special __closure property. The serializer uses that __closure property to figure out which variables are captured by the function.

    How you inject this transform depends on the webpack loader you're using. For ts-loader and awesome-typescript-loader, you can do the following:

    import { beforeTransform, afterTransform } from 'ts-closure-transform';
    // ...
    loader: 'ts-loader',
    options: {
      getCustomTransformers: () => ({
        before: [beforeTransform()],
        after: [afterTransform()]
      })
    }
    // ...

    Note that ts-closure-transform is strictly a dev dependency: there's no need to package it with your application.

  2. serialize-closures: a runtime library that defines the serialize and deserialize functions. These should work for any object graph as long as all source code has first been processed by ts-closure-transform.

Limitations

ts-serialize-closures works fairly well for modest object graphs, but it does have a number of limitations you should be aware of:

  • Variable-capturing functions defined in files that have not been transformed by ts-closure-transform cannot be deserialized correctly.

  • Serializing class definitions works, but only if they are first lowered to function definitions by the TypeScript compiler, i.e., the target is ES5 or lower.

  • Functions can only be serialized and deserialized once. There is no support for serializing a deserialized function.

About

TypeScript Serialization module

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 5

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy