{"_id":"@elliottcable/giraphe","_rev":"5-a7565c97b0adb0c4389b431ab6746d7d","name":"@elliottcable/giraphe","description":"A exceedingly-generic graph walking API.","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0-npmtest.1":{"author":{"name":"ELLIOTTCABLE","url":"http://ell.io/tt"},"name":"@elliottcable/giraphe","version":"1.0.0-npmtest.1","license":"ISC","description":"A exceedingly-generic graph walking API.","repository":{"type":"git","url":"git+https://github.com/elliottcable/giraphe.git"},"main":"./giraphe.js","scripts":{"test":"./test.sh","build":"./build.sh","prepublish":"./build.sh"},"directories":{"lib":"./","src":"./","test":"./Tests","doc":"./Docs","coverage":"./Docs/Coverage"},"babel":{"presets":["es2015","stage-2"],"plugins":["transform-runtime","transform-flow-comments"],"sourceMaps":"inline","compact":false,"env":{"coverage":{"plugins":["babel-plugin-espower","istanbul"]},"test":{"plugins":["babel-plugin-espower"]},"development":{"plugins":["babel-plugin-espower"]},"production":{"plugins":["babel-plugin-unassert"]}}},"nyc":{"all":true,"include":["giraphe.es6.js"],"extension":[".es6.js"],"require":["babel-register"],"sourceMap":false,"instrument":false},"mocha":{"ui":"bdd","reporter":"mocha-fivemat-reporter"},"dependencies":{"debug":"^2.2.0","lodash":"^4.13.1","babel-runtime":"^6.9.2"},"devDependencies":{"flow-bin":"^0.24.0","babel-cli":"^6.9.0","babel-register":"^6.9.0","babel-preset-es2015":"^6.9.0","babel-preset-stage-2":"^6.5.0","babel-plugin-transform-runtime":"^6.9.0","babel-plugin-transform-flow-comments":"^6.8.0","babel-plugin-espower":"^2.2.0","babel-plugin-unassert":"^2.1.0","babel-plugin-istanbul":"^2.0.0","mocha":"^2.5.3","power-assert":"^1.4.1","sinon":"2.0.0-pre.2","nyc":"^8.1.0"},"gitHead":"21d92d3307feab6b5c05f46a8dd46bc656df075c","bugs":{"url":"https://github.com/elliottcable/giraphe/issues"},"homepage":"https://github.com/elliottcable/giraphe#readme","_id":"@elliottcable/giraphe@1.0.0-npmtest.1","_shasum":"6851d8eb3690fdda64cdcd2ff4442e53f85bdcd4","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.5.0","_npmUser":{"name":"elliottcable","email":"npm@elliottcable.name"},"dist":{"shasum":"6851d8eb3690fdda64cdcd2ff4442e53f85bdcd4","tarball":"https://registry.npmjs.org/@elliottcable/giraphe/-/giraphe-1.0.0-npmtest.1.tgz","integrity":"sha512-1qANSokiycnvnX1xllu4RHhpeaGIWh7uBG03DrH6tVjwDazkb2u5G/cNBZhyFGiapUelk2s5KZuyuRxEX+fiDA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICfSOd5N/LWb46fuXrWIE5y7uNoa77YOei8s2kU34NJqAiBOf0WEry2YXHmTTPVJk4gKPgAyq3+p7oaZQS5vRd/XhQ=="}]},"maintainers":[{"name":"elliottcable","email":"npm@elliottcable.name"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/giraphe-1.0.0-npmtest.1.tgz_1483326240946_0.5244802166707814"}},"1.0.0-npmtest.2":{"author":{"name":"ELLIOTTCABLE","url":"http://ell.io/tt"},"name":"@elliottcable/giraphe","version":"1.0.0-npmtest.2","license":"ISC","description":"A exceedingly-generic graph walking API.","repository":{"type":"git","url":"git+https://github.com/elliottcable/giraphe.git"},"main":"./giraphe.js","scripts":{"test":"./test.sh","build":"./build.sh","prepublish":"./build.sh"},"directories":{"lib":"./","src":"./","test":"./Tests","doc":"./Docs","coverage":"./Docs/Coverage"},"babel":{"presets":["es2015","stage-2"],"plugins":["transform-runtime","transform-flow-comments"],"sourceMaps":"inline","compact":false,"env":{"coverage":{"plugins":["babel-plugin-espower","istanbul"]},"test":{"plugins":["babel-plugin-espower"]},"development":{"plugins":["babel-plugin-espower"]},"production":{"plugins":["babel-plugin-unassert"]}}},"nyc":{"all":true,"include":["giraphe.es6.js"],"extension":[".es6.js"],"require":["babel-register"],"sourceMap":false,"instrument":false},"mocha":{"ui":"bdd","reporter":"mocha-fivemat-reporter"},"dependencies":{"debug":"^2.2.0","lodash":"^4.13.1","babel-runtime":"^6.9.2"},"devDependencies":{"flow-bin":"^0.24.0","babel-cli":"^6.9.0","babel-register":"^6.9.0","babel-preset-es2015":"^6.9.0","babel-preset-stage-2":"^6.5.0","babel-plugin-transform-runtime":"^6.9.0","babel-plugin-transform-flow-comments":"^6.8.0","babel-plugin-espower":"^2.2.0","babel-plugin-unassert":"^2.1.0","babel-plugin-istanbul":"^2.0.0","mocha":"^2.5.3","power-assert":"^1.4.1","sinon":"2.0.0-pre.2","nyc":"^8.1.0"},"gitHead":"21d92d3307feab6b5c05f46a8dd46bc656df075c","bugs":{"url":"https://github.com/elliottcable/giraphe/issues"},"homepage":"https://github.com/elliottcable/giraphe#readme","_id":"@elliottcable/giraphe@1.0.0-npmtest.2","_shasum":"8d6550fdb78b372165ec29c5dc79d69d9608f0ec","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.5.0","_npmUser":{"name":"elliottcable","email":"npm@elliottcable.name"},"dist":{"shasum":"8d6550fdb78b372165ec29c5dc79d69d9608f0ec","tarball":"https://registry.npmjs.org/@elliottcable/giraphe/-/giraphe-1.0.0-npmtest.2.tgz","integrity":"sha512-0qgkOCReWDTxDoFI6zlZUT5NCQYE4QzL5N5L4PyOEN0+k+g8FOULIGu4Jqz/Z89WDYyB4BICqByNMswqGpGDYQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDoBD1/OE9vurk0tFqzQI0wdTL4dO/4vn+scssMUWNtkgIgZpooOxovNSbK6cskhJ/Qy0UfFZ4axTE+EsIA3HAxsSs="}]},"maintainers":[{"name":"elliottcable","email":"npm@elliottcable.name"}],"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/giraphe-1.0.0-npmtest.2.tgz_1483326765975_0.9283819610718638"}},"1.0.0":{"author":{"name":"ELLIOTTCABLE","url":"http://ell.io/tt"},"name":"@elliottcable/giraphe","version":"1.0.0","license":"ISC","description":"A exceedingly-generic graph walking API.","repository":{"type":"git","url":"git+https://github.com/elliottcable/giraphe.git"},"main":"./giraphe.js","scripts":{"test":"./test.sh","build":"./build.sh","prepublish":"./build.sh"},"directories":{"lib":"./","src":"./","test":"./Tests","doc":"./Docs","coverage":"./Docs/Coverage"},"babel":{"presets":["es2015","stage-2"],"plugins":["transform-runtime","transform-flow-comments"],"sourceMaps":"inline","compact":false,"env":{"coverage":{"plugins":["babel-plugin-espower","istanbul"]},"test":{"plugins":["babel-plugin-espower"]},"development":{"plugins":["babel-plugin-espower"]},"production":{"plugins":["babel-plugin-unassert"]}}},"nyc":{"all":true,"include":["giraphe.es6.js"],"extension":[".es6.js"],"require":["babel-register"],"sourceMap":false,"instrument":false},"mocha":{"ui":"bdd","reporter":"mocha-fivemat-reporter"},"dependencies":{"debug":"^2.2.0","lodash":"^4.13.1","babel-runtime":"^6.9.2"},"devDependencies":{"flow-bin":"^0.24.0","babel-cli":"^6.9.0","babel-register":"^6.9.0","babel-preset-es2015":"^6.9.0","babel-preset-stage-2":"^6.5.0","babel-plugin-transform-runtime":"^6.9.0","babel-plugin-transform-flow-comments":"^6.8.0","babel-plugin-espower":"^2.2.0","babel-plugin-unassert":"^2.1.0","babel-plugin-istanbul":"^2.0.0","mocha":"^2.5.3","power-assert":"^1.4.1","sinon":"2.0.0-pre.2","nyc":"^8.1.0"},"gitHead":"2a279789c409092052fba5526d887ea8fa817e0d","bugs":{"url":"https://github.com/elliottcable/giraphe/issues"},"homepage":"https://github.com/elliottcable/giraphe#readme","_id":"@elliottcable/giraphe@1.0.0","_shasum":"de26c6038045eeab8b1f08925f0a504fc5e1530f","_from":".","_npmVersion":"3.10.3","_nodeVersion":"6.5.0","_npmUser":{"name":"elliottcable","email":"npm@elliottcable.name"},"dist":{"shasum":"de26c6038045eeab8b1f08925f0a504fc5e1530f","tarball":"https://registry.npmjs.org/@elliottcable/giraphe/-/giraphe-1.0.0.tgz","integrity":"sha512-s95u6f1IhkL6v9eqQPjEETOKQztAYJYoWtMvxbT/dbAtqdmIw28eEVwMkP8J6W5eF7pynCjLF3iRWBW1B/gfWA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDHCGVpUS245pOwzZRjptG1yttIGBIdew7unFNw/GWuXgIhALDSgTSiyhY3g2J3JoAOGe3uGmxfxlWsAqQUP7BCphNq"}]},"maintainers":[{"name":"elliottcable","email":"npm@elliottcable.name"}],"_npmOperationalInternal":{"host":"packages-18-east.internal.npmjs.com","tmp":"tmp/giraphe-1.0.0.tgz_1483334340966_0.6726437092293054"}}},"readme":"Giraphe\n=======\nThis is an API stub for a generic graph-climbing library in JavaScript, extracted from (and\ndeveloped for) [Paws.js][]. It's intended to present the the same API for different use-cases, while\nsimultaneously optimizing for each use-case individually. (It does not currently do this.)\n\nThe primary purpose of Giraphe's `walk()` function is, given an arbitrary graph structure expressed\nin JavaScript objects, to allow you to *explore* that graph in a static fashion — given a set of\ncallbacks, to walk through the graph, both 1. ‘discovering’ new subgraphs that need to be recursed\ninto, and 2. ‘collecting’ nodes according to some critereon.\n\n\nInterface\n---------\n\n### The `Walker()` constructor\n\nThe default export, this must be called with an `options` argument, and it returns a `walk()`\nfunction as described by those options.\n\n```es6\nimport Walker from 'giraphe'\nconst walk = new Walker( ... )\n```\n\nThe passed options-object must have *exactly one* of the `keyer:` or `key:` properties:\n\n - **`key:`** — the most basic mode of operation, this expresses that nodes beloning to your graph\n   have unique `String`-ish identifiers, stored on the node-`Object` at the property with the given\n   name.\n\n   ```es6\n   const walk = new Walker({ key: 'id', ... })\n       , root = { id: 'foobar' }\n\n   walk(root, ...)\n   ```\n\n - **`keyer:`** — for more flexibility, you may instead provide a function to generate a unique key\n   for a given node. The function you provide as the `keyer` will be invoked with the object to be\n   uniquely identified, and must return a `String` unique to that Object.\n\n   ```es6\n   const identify = node => /* generate key! */\n       , walk = new Walker({ keyer: identify, ... })\n       , root = new MyNodeType\n\n   walk(root, ...)\n   ```\n\nThe options must also include *exactly one* of the `class:` or `predicate:` properties:\n\n - **`class:`** — again, this causes the simplest mode of operation; when passed a JavaScript\n   `Function` (i.e. a “class”), this will cause the walking-function to use a simple `instanceof`\n   check to determine whether a touched JavaScript object is a node in your graph or not.\n\n   ```es6\n   const walk = new Walker({ key: ..., class: MyNodeType })\n       , root = new MyNodeType\n\n   walk(root, ...)\n   ```\n\n - **`predicate:`** — when functioning across JavaScript contexts, or otherwise operating on a graph\n   of noes of non-homogenous JavaScript type, you may instead provide a `predicate` function which\n   will indicate to Giraphe whether a given JavaScript `Object` is a node in your graph or not.\n\n   ```es6\n   const isNode = node => /* verify nodey-ness! */\n       , walk = new Walker({ key: ..., predicate: isNode })\n       , root = new MyNodeType\n\n   walk(root, ...)\n   ```\n\n\n### The produced `walk()` function\nOnce configured, Giraphe will return to you a function-object, which is to be called with a `root`\nnode and a collection of various sorts of `callbacks`. The returned `walk()` function may be called\neither function-style, or method-style:\n\n```es6\nconst walk = new Walker( ... )\nwalk(root, ...)\n\nMyNodeClass.prototype.walk = walk\nroot.walk(...)\n```\n\nThe first argument to `walk()` (or alternatively the object upon which it is invoked, if it is\ninvoked method-style) must be an object of the `class` passed to the `Walker` constructor (or one\nsatisfying the `predicate`, if such was passed instead — henceforth, I'll just call such an object\n“a node.”); that node will be the first walked, that is, the root of the subgraph that gets walked.\n\nOther arguments must be functions; these behave as callbacks manipulating the behaviour of the\nrecursive `walk()` process. Such callbacks must behave in one of two ways: as a so-called\n‘supplier’, or as a ‘filter.’\n\nAll callbacks are invoked with the same arguments (*none of which* may be safely modified):\n\n - The `current` node being visited,\n - the `parent` node that was being visited when a supplier-callback yielded that `current` node,\n - a set-map (`key`-to-node-object) of nodes `supplied` by *prior* suppliers during *this visit*,\n - a set-map of *all* nodes `seen` during the walk thus far (including rejected nodes),\n - and the complete list of `callbacks` with which the current `walk()` is operating.\n\nWhen all discovered nodes in the graph have been exhausted, `walk()` produces a final object-mapping\nof nodes; the properties of which are the unique-keys of all collected (and non-rejected) nodes,\neach with the corresponding node itself as the value.\n\n#### ‘Supplier’ callbacks\nSuppliers are how `walk()` recurses into your graph-structure. At each node, additional nodes may\nbe ‘discovered’ by your supplier-callback; these'll be added to the set of nodes pending visitation.\n\nSuppliers may indicate further nodes for visitation by,\n\n - returning a node directly:\n\n   ```es6\n   root.walk(node => { return node.child })\n   ```\n\n - returning an `Array` of nodes:\n\n   ```es6\n   root.walk(node => { return [node.left, node.right] })\n   ```\n\n - returning an object-mapping of nodes (such as that returned from another `walk()` process):\n\n   ```es6\n   root.walk(node => { return node.walk_children() })\n   ```\n\n(Note that, although returning `undefined` technically makes a callback a ‘filter’, it counts as a\n pass; so it's equivalent to a supplier that adds nothing. However, filter-vs-supplier behaviour may\n change in future releases, especially w.r.t. caching!)\n\n#### ‘Filter’ callbacks\nIf suppliers are how you find new nodes to visit, filters are how you select which of those nodes\ncontribute to the overall result of the `walk()`. Where suppliers operate on descendants of the\n`current` node being visited, filters operate on that `current` node itself.\n\nAny callback returning a boolean value is treated as a filter.\n\nThe default behaviour of a filter (i.e. if it returns `undefined`), is to *pass* the `current` node\n— i.e. as a noop, simply let it, and any nodes `supplied` by other callbacks, through into the final\noutput of `walk()`.\n\n```es6\nroot.walk(node => { return node.is_blue || node.is_green })\n```\n\nHowever, if a callback explicitly returns boolean `false`, then it's considered to *reject* the\n`current` node — despite having been ‘supplied’ by a previous callback, this node will not be\nincluded in the results of the `walk()`; and any *newly*-`supplied` nodes from the current walk-step\nwill be discarded¹ as well.\n\n```es6\nroot.walk(node => { return false if node.age >= 12 })\n```\n\nSuch rejection is short-circuiting — the current walk-step is aborted, no further callbacks (of\neither type) are evaluated, any nodes collected via the rejected `current` node during this step\nwill be discarded, so on and so forth.\n\n>  1. (Of note, this simply invalidates their *discovery* by way of the current, rejected node —\n>      they are not, themselves, ‘rejected’; and may be re-supplied by a different walk-step / be\n>      re-discovered by a different path through your graph.)\n\n\n### Examples\n\n```es6\nconst MyNode = function(){\n   this._children = new Array\n   this.id = MyNode.max = (MyNode.max || 0) + 1 }\n\nMyNode.prototype.walk = new Walker({ key: 'id', class: MyNode })\nMyNode.prototype.descendants = MyNode.prototype.walk(node => node.children)\n\n// ... NYI\n```\n\n\nWhy?\n----\nThis exists because I got tired of writing *almost* the same graph-walking function, over and over,\nfor Paws.js; while each function was slightly different from the previous one, and yet occured in a\n‘hot’ enough location to preclude using a truly generic `walk()` function for each situation.\n\nThe *intention*, unfulfilled, was to pre-‘compile’ optimized graph-walking functions for each\nsituation, based on the `options` passed to the `Walker` constructor; this would allow me to\ncentralize testing efforts and interface design (the API) to this single library. My first attempt\nat that task was laughable (it involved mustache templates. [Seriously][horrible mess].); and thus,\nfor now, this library is simply going to be an external API, with a generic (slow) `walk()`\nimplementation satisfying *all* of my needs; however, I still hope to eventually extract the\nnecessary optimizations into this library.\n\n\n   [Paws.js]: <https://github.com/ELLIOTTCABLE/Paws.js#readme> \"The Paws programming language\"\n   [horrible mess]: <https://github.com/ELLIOTTCABLE/giraphe/blob/horrible-mess+/walk.es6.js.mustache#L10-L127>\n      \"My last attempt at a pre-compiled walk() function, in the git history\"\n","maintainers":[{"name":"elliottcable","email":"npm@elliottcable.name"}],"time":{"modified":"2022-06-12T17:31:46.094Z","created":"2017-01-02T03:04:01.613Z","1.0.0-npmtest.1":"2017-01-02T03:04:01.613Z","1.0.0-npmtest.2":"2017-01-02T03:12:48.101Z","1.0.0":"2017-01-02T05:19:01.628Z"},"homepage":"https://github.com/elliottcable/giraphe#readme","repository":{"type":"git","url":"git+https://github.com/elliottcable/giraphe.git"},"author":{"name":"ELLIOTTCABLE","url":"http://ell.io/tt"},"bugs":{"url":"https://github.com/elliottcable/giraphe/issues"},"license":"ISC","readmeFilename":"README.markdown"}