{"id":16115229,"url":"https://github.com/pvande/pointed","last_synced_at":"2026-04-29T17:04:45.084Z","repository":{"id":25250899,"uuid":"28675800","full_name":"pvande/Pointed","owner":"pvande","description":"Atomic data manipulation and traversal","archived":false,"fork":false,"pushed_at":"2015-07-15T16:39:25.000Z","size":162,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-02-06T22:52:55.725Z","etag":null,"topics":["coffeescript","javascript","pointer","zipper"],"latest_commit_sha":null,"homepage":null,"language":"CoffeeScript","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/pvande.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}},"created_at":"2014-12-31T21:45:23.000Z","updated_at":"2017-11-01T02:12:07.000Z","dependencies_parsed_at":"2022-09-21T02:01:38.810Z","dependency_job_id":null,"html_url":"https://github.com/pvande/Pointed","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/pvande/Pointed","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pvande%2FPointed","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pvande%2FPointed/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pvande%2FPointed/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pvande%2FPointed/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pvande","download_url":"https://codeload.github.com/pvande/Pointed/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pvande%2FPointed/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32435122,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T13:34:34.882Z","status":"ssl_error","status_checked_at":"2026-04-29T13:34:29.830Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["coffeescript","javascript","pointer","zipper"],"created_at":"2024-10-09T20:18:07.806Z","updated_at":"2026-04-29T17:04:45.065Z","avatar_url":"https://github.com/pvande.png","language":"CoffeeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Pointed\n=======\n\n\u003e   Admiring the grand structure of the Complex, I wandered ahead, mindless of\n\u003e any particular goal.  Engineering at this scale was in a league of its own,\n\u003e and worth taking time to appreciate.  Even more impressive, however, was the\n\u003e intelligence that sat behind the scenes, subtly influencing the guests – and\n\u003e me – to optimize uncountable factors.\n\u003e\n\u003e   It was impossible to get truly lost in the Complex, as only the thought of\n\u003e a specific location triggered automated responses intended to guide you\n\u003e there.  A subtle shift in lighting here, a minor increase in air pressure\n\u003e just behind you, and a thousand other changes too small to notice would\n\u003e ensure that you arrived there.  The experience was uncanny: on even my\n\u003e first visit I \"knew\" exactly how to get anywhere, but I couldn't have\n\u003e verbalized it if I'd tried.  Not that I had any reason to try, since every\n\u003e other visitor had the same \"sense\" of direction.\n\u003e\n\u003e   Even after living here for three years, I was still amazed by the Complex.\n\u003e The technical skill, the fine tuning, and the ambitious scale all culminated\n\u003e in one of the most sophisticated places on Earth, and the seeming simplicity\n\u003e of it all made me smile every time I thought about it.  I thought briefly\n\u003e about taking my stroll through the arboretum, and felt the world around me\n\u003e re-orient as the Complex carved out a path, and gently Pointed me in the\n\u003e right direction.\n\nPointed implements an intra-graph reference mechanism, similar to a functional\n[zipper].  This library aims to be as lightweight and comprehensible as\npossible, while still maintaining useful performance and compatibility profiles.\n\nPut another way, Pointed is a tool for creating navigational maps through a data\nstructure.  These maps (or `Pointer`s) make it easy access, update, and monitor\nchanges to the data structure, making it well suited for scoping responsibility\nand for use in declarative UI toolkits, like [React].\n\n``` coffeescript\n  Pointer = require 'pointed'\n\n  data = { nested: { data: 'structure' } }\n  ptr = Pointer(data)\n\n  subptr = ptr.get('nested', 'data')\n  subptr.value()  # =\u003e 'structure'\n\n  subptr = ptr.update (val) -\u003e val.slice(0, 3)\n  subptr.value()  # =\u003e 'str'\n  ptr.value()  # =\u003e { nested: { data: 'str' } }\n```\n\n## Interface\n\n### `Pointer(data)`\nReturns a new Pointer instance for the root of the given `data` structure.\n\n### `Pointer::get(key...)`\nReturns a new Pointer instance for an element of the data structure represented\nby the pointer.\n\n### `Pointer::value(key...)`\nReturns the underlying value for an element of the data structure represented by\nthe pointer.\n\n### `Pointer::update((oldData) -\u003e newData)`\nUpdates the data underlying the pointer based on the value returned by the given\nfunction.  This will emit [a \"swap\" event](#events) on this pointer and all\npointers that contain this one.\n\n### `Pointer::map((ptr, key) -\u003e obj)`\nIterates over the underlying array (or object), generating pointers for each\nelement, and passes each pointer and the index (or key) to the given function.\nThe values returned by the function will be collected and returned as an array.\n\n### `Pointer::isEqual(otherPointer)`\nChecks to see if this pointer and the given pointer both refer to the same path\nand referenced equivalent data when they were created.\n\nNote that two pointers that share the same underlying data and have the same\npath will *always* return identical results, permitting pointers to be both\n\"long-lived\" and always reflect current data.  It is for this reason that\n\"Pointer equality\" takes creation time into account – path equality alone does\nnot answer the most common question, \"Has this data changed?\"\n\n### `Pointer::hash`\nA digest of the data represented by this hash.  Useful as a generic content key,\nand for quickly testing data equality.\n\n## Events\n\n### `Pointer::on(event, fn)`\nAdds a callback function for the named event to the pointer.\n\n### `Pointer::off(event, fn)`\nRemoves a callback function for the named event to the pointer.\n\n### `Pointer::emit(event, args...)`\nFires the named event for this pointer and other pointers to the same data,\npassing the given arguments to the callback functions.\n\n## Guarantees\n\n* `Pointer#get` will always return a Pointer (possibly to an unknown property).\n* `Pointer#value` will return `undefined` if the pointer cannot be resolved.\n* Two pointers representing the same absolute path will return the same object.\n* `Pointer#update` will not change object references if the data is unchanged.\n  * Similarly, `Pointer#update` will not fire events if the data is unchanged.\n\n## Notable Behavior\n\n* Data that cannot be serialized to JSON is not currently supported.\n* Events are always fired on a \"fresh\" pointer instance.  This makes it easy to\n  compare \"stale\" pointers against a more current state.\n* `Pointer#update` will *not* fire a 'swap' event for pointers to keys beneath\n  it.  If this is behavior you need, it's recommended that you make smaller\n  changes to more deeply nested pointers.\n\n  ``` coffeescript\n  P = Pointer({ a: { b: 1 } })\n  A = P.get('a')\n  AB = P.get('a', 'b')\n\n  # This call will fire events on `P` and `A`, but not `AB`.\n  A.update (obj) -\u003e\n    obj.b += 10\n    return obj\n\n  # This call will fire events on `P`, `A`, and `AB`.\n  AB.update (value) -\u003e value + 10\n  ```\n\n## Undefined Behavior\n\n* Directly modifying the underlying data structure is not encouraged.\n  * Use `Pointer#update` to make changes instead.\n\n## TODO\n\n* History\n  * `undo`, `redo`\n* `shouldComponentUpdate` Helpers\n* Better Object cloning\n\n[zipper]: https://www.haskell.org/haskellwiki/Zipper\n[React]: https://github.com/facebook/react\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpvande%2Fpointed","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpvande%2Fpointed","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpvande%2Fpointed/lists"}