{"id":21593029,"url":"https://github.com/jonabrams/elsa","last_synced_at":"2025-04-10T23:32:21.693Z","repository":{"id":143485643,"uuid":"89099742","full_name":"JonAbrams/elsa","owner":"JonAbrams","description":"A babel plugin for replacing object and array literals with immutable versions","archived":false,"fork":false,"pushed_at":"2018-12-29T05:26:27.000Z","size":36,"stargazers_count":116,"open_issues_count":0,"forks_count":10,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-09T19:05:10.226Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JonAbrams.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-04-22T21:17:36.000Z","updated_at":"2024-02-21T13:02:47.000Z","dependencies_parsed_at":null,"dependency_job_id":"8c139080-ead4-4759-b825-d4dc372344af","html_url":"https://github.com/JonAbrams/elsa","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JonAbrams%2Felsa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JonAbrams%2Felsa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JonAbrams%2Felsa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JonAbrams%2Felsa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JonAbrams","download_url":"https://codeload.github.com/JonAbrams/elsa/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248316424,"owners_count":21083441,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-24T17:10:59.768Z","updated_at":"2025-04-10T23:32:21.686Z","avatar_url":"https://github.com/JonAbrams.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Elsa\n\n\u003e Mutability is dangerous, [_let it go_](https://www.youtube.com/watch?v=A_DaizJnnJQ)!\n\nBabel plugin that replaces object and array literals with immutable versions… that have super powers!\n\n[![Build Status](https://travis-ci.org/JonAbrams/elsa.svg?branch=master)](https://travis-ci.org/JonAbrams/elsa)\n\n## Usage\n\nElsa is a babel plugin, to make use of it, you need to install it:\n\n    npm install --save babel-plugin-elsa\n\nAdd elsa as a plugin to your `.babelrc` config file (or babel section of `package.json`):\n```json\n{\n  \"plugins\": [\"babel-plugin-elsa\"]\n}\n```\n\n## Purpose\n\nImmutability is **cool** these days. By never altering the contents of an object or array, and instead cloning them when you want to make a change, you [avoid common bugs](http://www.yegor256.com/2014/06/09/objects-should-be-immutable.html). It's especially popular in [React](https://facebook.github.io/react/) development, but by no means exclusive to React.\n\nThere are great libraries out there like [Immutable.js](https://facebook.github.io/immutable-js/) that\nprovide a bunch of classes for making immutable objects, but wouldn't it be **frosty** to turn the default object and arrays into immutable objects?\n\nDon't worry, there are no more puns past this point, they've been put on **ice**.\n\nElsa does two things:\n- It turns each [object literal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Object_literals) into a `FrozenObject`.\n- It changes each [array literal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Array_literals) into a `FrozenArray`.\n\nBoth `FrozenObject`s and `FrozenArray`s are immutable classes included with Elsa. If you try to change their contents, they'll raise\na `TypeError` since they've been frozen with [`Object.freeze`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze). Assuming you have [strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) enabled (which you ought to do).\n\nElsa will:\n```javascript\n// Turn this:\nconst person = {\n  name: 'Jon',\n  skills: ['ruby', 'javascript']\n};\n\n// into:\nconst person = new FrozenObject({\n  name: 'Jon',\n  skills: new FrozenArray('ruby', 'javascript')\n});\n```\n\nWhy create these new classes instead of just calling `Object.freeze`? To give them super powers, read on!\n\n## FrozenArray\n\nElsa turns all array literals (e.g. `const coolNumbers = [1,5,-4,20];`) into instances of `FrozenArray`.\n\n`FrozenArray` inherits from JavaScript's built-in Array. This means it has a `.length`, is an instance of `Array`, and any of the methods that you'd expect like `.forEach` and `.map`.\n\nThe methods on `Array` that would typically mutate the array are reimplemented on`FrozenArray` to\ninstead return a fresh instance of `FrozenArray` with changes applied. This includes `push`, `pop`,\n`unshift`, `shift`, `sort`, `reverse`, `splice`, and `fill`.\n\n`slice`, `map`, and other methods that already return new arrays are still available, but\nreturn `FrozenArray` instances instead of a normal mutable array.\n\n`pop` and `shift` return both the _modified_ arrays and the shifted/popped values as two elements inside an array. That way you can do: `[arr, poppedVal] = arr.pop()`.\n\n**Examples:**\n- `push`: `new FrozenArray(1,2,3).push(5)` -\u003e `[1, 2, 3, 5]`\n- `pop`: `new FrozenArray(1,2,3).pop()` -\u003e `[[1, 2], 3]`\n- `unshift`: `new FrozenArray(1,2,3).shift(0)` -\u003e `[0,1,2,3]`\n- `shift`: `new FrozenArray(1,2,3).shift()` -\u003e `[[2,3], 1]`\n- `sort`: `new FrozenArray(2,1,3).sort((a,b) =\u003e a - b)` -\u003e `[1,2,3]`\n\n**Note:** Return values are all instances of FrozenArray\n\n## FrozenObject\n\nElsa turns all object literals (e.g. `const dog = { name: 'Loki', age: 4 };`) into instances of `FrozenObject`.\n\n`FrozenObject` is identical to a normal JavaScript object, but it has been frozen by `Object.freeze`\nand has a special method called `update`, provided by [immutability-helper](https://github.com/kolodny/immutability-helper).\n\nTo see all the ways you can get a clone, with changes applied, using `update` see the immutability-helper docs: https://github.com/kolodny/immutability-helper\n\n**One example:**\n```javascript\nconst dog = { name: 'Loki', age: 4, friends: ['Waffles', 'Mochi'] };\nconst dogClone = dog.update({ name: { $set: 'Loki 2.0' }, friends: { $push: ['Seamus'] } });\n// dogClone now contains { name: 'Loki 2.0', age: 4, friends: ['Waffles', 'Mochi', 'Seamus'] }\n```\n\n## Opting out of FrozenArray and FrozenObject\n\nElsa will ignore arrays created with `new Array(1,2,3)` or `Array.of(1,2,3)`, which will produce old\nfashioned mutable arrays.\n\nTo create mutable objects, you can do `new Object({ name: 'Loki' })`, which Elsa will skip over, resulting in old fashioned mutable objects.\n\n## Gotchas and tips\n\n- Elsa will only alter object and array literals. If you create an object using a function of `new` constructor, it won't be frozen (at least not by Elsa). Only `[…]` and `{…}` are frozen by Elsa.\n- Some libraries expect to receive mutable objects as their parameters. If you receive type errors in\nlibraries that you use, try sending in an object created with `new Object({…})`.\n- Elsa only converts your code. Babel, and therefore Elsa, doesn't convert 3rd party modules. This means\nthat any objects produced by libraries won't be frozen.\n- You can freeze objects returned by libraries by wrapping it with `new FrozenObject(…)`.\n- If you don't use Elsa as a Babel plugin, you can still use `FrozenArray` and `FrozenObject` with your code. Just do `import FrozenArray from 'babel-plugin-elsa/frozen_array'` and/or `import FrozenObject from 'babel-plugin-elsa/frozen_object'`.\n\n## Sample App\n\nI've written a very basic todo app (of course) that makes use of Elsa.\n\n- [Source with Elsa](https://github.com/JonAbrams/todo-elsa)\n- [Source without Elsa](https://github.com/JonAbrams/todo-elsa/tree/07e325445ad3fcb6a1244f85bbbcdac43033d13a)\n- [Diff](https://github.com/JonAbrams/todo-elsa/commit/07e325445ad3fcb6a1244f85bbbcdac43033d13a)\n- [Live](https://todo-elsa-whylddtmuu.now.sh)\n\n## License\n\nISC\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonabrams%2Felsa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonabrams%2Felsa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonabrams%2Felsa/lists"}