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 🙏

© 2024 – Pkg Stats / Ryan Hefner

persistent-clazz

v1.1.2

Published

A collection of utilities for making lightweight persistent objects in JS.

Downloads

1

Readme

persistent-clazz

A collection of utilities for making lightweight persistent objects (and hierarchies of such) in JS.

This library facilitates a specific style of OOP which favours composition over inheritance and immutable over mutable.

quote

##Motivation/About

Making a user friendly persistent API is tricky, especially when dealing with nested structures. You have to explicitly construct a new object on each change. You cannot just call a method of an object you reference - you have to update the reference with the new version.

However fluent persistent API's are also a real pleasure to use and they work as a very nice alternative to functional composition. JavaScript already has facilities for creating immmutable datastructures - the Object.freeze method so all it takes to finish up the job is to define a couple of very simple helpers.

##Example

The following example defines two types, Point and Circle, where both of them are persistent.

const {clazz, getter, setter, alias, lens, assign} = require('../src/main')

const number = (val) => {
  if (typeof val === 'number') {
    return val
  } else {
    throw new Error(val + ' is not a number')
  }
}

//Define a class-like object using the 'clazz' helper (or with any other)
const Point = clazz({
  // Declare properties and their default values
  x: 0, 
  y: 0,
  // Easily define getters and immutable setters with support for validation:
  setX: setter('x', number),
  setY: setter('y', number),
  getX: getter('x'),
  getY: getter('y'),
  // Define normal methods
  toString(){
    return `(${this.x}, ${this.y})`
  },
})

exports.getterSetter = ({throws, equal, done}) => {

  // Create the object as you normally would.
  point = Point({x:1, y:2})

  // Apply transformations to an object to get a new one
  newPoint = point
              .setX(2)
              .setY(3) 

  // The reference to the new object is updated
  equal(newPoint.toString(), '(2, 3)')

  // Old value remains unchanged
  equal(point.toString(), '(1, 2)' )

  // Validation functions passed in to the setter are automatically  called
  throws(()=> { point.setX('a')} )

  // The properties you pass in the constructor are validated against the default values in the prototype
  throws(()=> Point({x:'1', y:'2'})) // ""x" is set to a value of type "string" in the constructor, but it is a "number" in the object prototype."
  done()
}


const Circle = clazz({
  center:Point(),
  radius: 0,

  //Create aliases  methods of member objects
  printCenter: alias('center', 'toString'),
  
  // Create lenses for modifying properties of member objects.
  setX:lens('center', 'setX'),
  setY:lens('center', 'setY'),

  // Use the low level 'assign' method to define custom modification methods without also defining explicit setters
  changeSize (amount) {
    return this.assign({radius: this.radius + amount})
  }
})

exports.hierarchies = ({throws, equal, done}) => {
  // When there is no constructor defined, you just pass a plain object that you want to use:
  const circle = Circle({radius:1})

  // You can use methods for both the host and member objects.
  biggerCircle = circle
                  .changeSize(1)
                  .setX(10)
                  .setY(10)

  equal(biggerCircle.radius, 2)
  equal(biggerCircle.printCenter(), '(10, 10)')
  //
  //lenses and aliases cannot be created if there are no default values for the properties
  throws(() => clazz({
    unexistingMethod: lens('unexistingProperty', 'method')
  })) // The property "unexistingProperty" is undefined in the clazz please set a default value for the property before making an lens
  
  //lenses and aliases cannot be created if there are no default values for the properties
  throws(() => clazz({
    center:Point(),
    unexistingMethod: lens('center', 'unexistingMethod')
  })) // The object that is stored in "center" does not have a method "unexistingMethod" You cannot create an lens for an unexisting method

  done()
}

Functions

clazz(proto) ⇒ function

Creates a class-like object constructor.

Kind: global function
Returns: function - An object constructor which calls the prototype's constructor method and then sets the prototype of the resulting object to proto.

| Param | Type | Description | | --- | --- | --- | | proto | object | The prototype. It can contain a key called constructor with function which must return an object. If it does, this function is used as the object's constructor. If it does not, a default constructor is used. It can also contain a key called properties with a plain object specifying all properties that the object can have: default, lens, alias. See below. |

assign(source, target) ⇒ object

Applies a transformation to one or several properties of an object and returns a transformed object with the same prototype and the same values of non-altered properties.

Kind: global function
Returns: object - A new version of the instance object.

| Param | Type | Description | | --- | --- | --- | | source | object | The object which you want to transform. | | target | object | A plain object containing one or several keys which are to be changed or added to the instance, along with their new values. Multiple targets are also supported. |

remove(source, target) ⇒ object

Applies a transformation to one or several properties of an object and returns a transformed object with the same prototype and the same values of non-altered properties.

Kind: global function
Returns: object - A new version of the instance object.

| Param | Type | Description | | --- | --- | --- | | source | object | The object which you want to transform. | | target | object | A plain object containing one or several keys which are to be changed or added to the instance, along with their new values. Multiple targets are also supported. |

getter(key) ⇒ function

Creates a method that retrieves the value of a property.

Kind: global function
Returns: function - A function which when attached to an object returns the current value of the property.

| Param | Type | Description | | --- | --- | --- | | key | string | The key of the property. |

setter(key) ⇒ function

Creates a method that changes the value of a property (by creating a new version of the object).

Kind: global function
Returns: function - A function which when attached to an object returns a new version of the object to which it is attached, where the value of key is changed changed to the one passed as an argument.

| Param | Type | Description | | --- | --- | --- | | key | string | The key of the property. |

alias(key, methodName) ⇒ function

Creates a method that calls another method on one of the values stored in the object and returns the result. May be used for creating shorthands for calling a getter.

Kind: global function
Returns: function - A function which when attached to an object calls the aliased method with the arguments given to it and returns the result.

| Param | Type | Description | | --- | --- | --- | | key | string | The key where the aliased object is stored. | | methodName | string | The name of the method. |

lens(key, methodName) ⇒ function

A combination between set and alias. Creates a method that modifies an object's key and returns a new version of the object with the new version of the key. Can be for creating shorthands for calling a setter.

Kind: global function
Returns: function - A function which when attached to an object calls the aliased method with the arguments given to it and returns a new version of the object where the value of key is replaced with the result of the method.

| Param | Type | Description | | --- | --- | --- | | key | string | The key where the aliased object is stored. | | methodName | string | The name of the method. The method should return a new version of the object. |