{"id":18476068,"url":"https://github.com/ducin/sygnalyze","last_synced_at":"2025-04-08T13:32:39.253Z","repository":{"id":222565812,"uuid":"757485457","full_name":"ducin/sygnalyze","owner":"ducin","description":"Enhanced 🚦 Angular Signals 🚦 with Super Powers!","archived":false,"fork":false,"pushed_at":"2024-02-18T19:01:57.000Z","size":586,"stargazers_count":9,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-02-18T22:22:26.687Z","etag":null,"topics":["angular","ngrx","signals"],"latest_commit_sha":null,"homepage":"https://stackblitz.com/edit/sygnalyze","language":"TypeScript","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/ducin.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}},"created_at":"2024-02-14T15:39:19.000Z","updated_at":"2024-02-18T20:06:17.000Z","dependencies_parsed_at":"2024-02-15T00:29:02.965Z","dependency_job_id":null,"html_url":"https://github.com/ducin/sygnalyze","commit_stats":null,"previous_names":["ducin/sygnalyze"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ducin%2Fsygnalyze","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ducin%2Fsygnalyze/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ducin%2Fsygnalyze/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ducin%2Fsygnalyze/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ducin","download_url":"https://codeload.github.com/ducin/sygnalyze/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223320055,"owners_count":17126022,"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":["angular","ngrx","signals"],"created_at":"2024-11-06T10:36:06.827Z","updated_at":"2024-11-06T10:36:07.592Z","avatar_url":"https://github.com/ducin.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ![Sygnalyze](./assets/logo/sygnalyze-logo-200.png)\n\nEnhance 🚦 Angular Signals 🚦 with Super Powers!\n\n- [](#)\n  - [Installation](#installation)\n  - [Online Demo](#online-demo)\n  - [Why?](#why)\n  - [API](#api)\n    - [`sygnal`](#sygnal)\n      - [readonly `update`](#readonly-update)\n      - [`draftUpdate(mutatingCallback)`](#draftupdatemutatingcallback)\n    - [`memento` / `withMemento(writableSignal)`](#memento--withmementowritablesignal)\n    - [`toggle` / `withToggle(writableSignal)`](#toggle--withtogglewritablesignal)\n    - [`immutablePatchState`](#immutablepatchstate)\n\n## Installation\n\n`npm i sygnalyze`\n\n## Online Demo\n\n👉 [stackblitz.com/edit/sygnalyze](https://stackblitz.com/edit/sygnalyze)\n\n## Why?\n\n- `sygnal` is a tiny wrapper which improve Angular `signal` DX\n- that means that 100% runtime of Angular signals is preserved and are meant to be always compatible\n- i.e. `computed`, `effects`, `toSignal`/`toObservable` will work with `sygnal` the same way as with `signal`\n\n## API\n\n### `sygnal`\n\nEnhanced Angular Signal - with 2 differences:\n\n#### readonly `update`\n\nThe `update` method parameter (current value) is `DeepReadonly` in order to avoid unintentional mutations\n\n```ts\nimport { sygnal } from 'sygnalyze'; \n\nconst item = sygnal({\n  name: 'john',\n  age: 40\n})\n\nitem.update(current =\u003e ...)\n//          ^? current is DeepReadonly\n```\n\n#### `draftUpdate(mutatingCallback)`\n\nAn additional method `draftUpdate(mutatingCallback)` allows to mutate the current value of the signal, but thanks to using `immer`, the value is replaced with an immutable \n\n```ts\nimport { sygnal } from 'sygnalyze'; \n\nconst item = sygnal({\n  name: 'john',\n  age: 40\n})\n\nitem.draftUpdate(draft =\u003e {\n  draft.age++;\n})\n```\n\nIn above code, a new object is set as the value, so the signal notifies all its dependents.\n\n### `memento` / `withMemento(writableSignal)`\n\nMake a snapshot (*memento*) of the signal's value at a certain point in time. Whenever memento gets restored, the signal goes back to that value.\n\n```ts\nimport { signal } from '@angular/core';\nimport { memento, withMemento, Memento } from 'sygnalyze'\n\nexport class TheComponent {\n  item = memento({ age: 40 }) // WritableSygnal\n  // or:\n  item = withMemento(signal({ age: 40 })) // original Signal\n  \n  ...\n\n  memento?: Memento\n\n  createMemento(){\n    this.memento = this.item.memento()\n  }\n\n  restoreMemento(){\n    this.memento?.restore()\n  }\n}\n```\n\n### `toggle` / `withToggle(writableSignal)`\n\nCreates a boolean signal with simple `toggle()` updating method.\n\n```ts\nimport { signal } from '@angular/core';\nimport { toggle, withToggle } from 'sygnalyze'\n\nexport class TheComponent {\n  showTheThing = toggle(true) // Sygnal\n  // or:\n  showTheThing = withToggle(signal(true)) // original Signal\n\n  ...\n\n  theMethod(){\n    this.showTheThing.toggle()\n  }\n}\n```\n\n### `immutablePatchState`\n\nThe NGRX Signal Store `patchState` function enhanced with [`immer` immutability](https://immerjs.github.io/immer/):\n\n```ts\nimport { immutablePatchState } from 'sygnalyze/ngrx'\n\nexport const Store = signalStore(\n  withMethods((store) =\u003e ({\n    updateOrder(order: 'asc' | 'desc'): void {\n      immutablePatchState(store, (draft) =\u003e { draft.filter.order = order });\n    },\n  })\n)\n```\n\nThe `immutablePatchState` function callback can now **mutate** the state draft object and return nothing. `immer` will create a new object by applying all recorded changes. You don't have to worry about applying immutable changes manually.\n\nCompare with default approach:\n\n```ts\nimport { signalStore, withMethods, ... } from '@ngrx/signals'\nimport { immutablePatchState } from 'sygnalyze/ngrx'\n\nexport const Store = signalStore(\n  //...\n  withMethods((store) =\u003e ({\n    // state: WritableDraft\u003cStateType\u003e\n    updateOrderMutative(order: 'asc' | 'desc'): void {\n      immutablePatchState(store, (draft) =\u003e { draft.filter.order = order });\n    },\n    // BEFORE: having to apply immutability manually by spread operator:\n    updateOrder(order: 'asc' | 'desc'): void {\n      patchState(store, (state) =\u003e ({ filter: { ...state.filter, order } }));\n    },\n  })\n)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fducin%2Fsygnalyze","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fducin%2Fsygnalyze","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fducin%2Fsygnalyze/lists"}