{"id":20189330,"url":"https://github.com/bugs181/timegraph","last_synced_at":"2026-05-12T00:32:19.477Z","repository":{"id":94470080,"uuid":"162840455","full_name":"bugs181/TimeGraph","owner":"bugs181","description":"TimeGraph library for the Gun bounty","archived":false,"fork":false,"pushed_at":"2019-01-28T03:29:29.000Z","size":328,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-03T07:15:20.673Z","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":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bugs181.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2018-12-22T20:22:15.000Z","updated_at":"2019-01-28T11:06:36.000Z","dependencies_parsed_at":"2023-07-14T23:00:43.094Z","dependency_job_id":null,"html_url":"https://github.com/bugs181/TimeGraph","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bugs181/TimeGraph","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bugs181%2FTimeGraph","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bugs181%2FTimeGraph/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bugs181%2FTimeGraph/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bugs181%2FTimeGraph/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bugs181","download_url":"https://codeload.github.com/bugs181/TimeGraph/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bugs181%2FTimeGraph/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27377919,"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","status":"online","status_checked_at":"2025-11-30T02:00:05.582Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2024-11-14T03:35:59.577Z","updated_at":"2025-11-30T05:03:33.297Z","avatar_url":"https://github.com/bugs181.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# !!! Work in Progress !!!\n\n# TimeGraph\nTimeGraph library for the [Gun TimeGraph bounty](https://gun.eco/docs/Bounty#-5k-reward-for-timegraph)\n\n# Notes:\n* Adds special TimeGraph indexes to the root of data.\n* This addition goes a little further than the original TimeGraph library by providing methods to work with time-data, streamed to normal gun operations.\n* Shim provided for Backwards compatibility with existing API\n* May cause problems for multiple chained `.time()` API (needs testing)\n\n# Features:\n* TimeGraphs can be synced across peers. Can build a wire adapter to filter them out if you so desire.\n* No special methods needed, works with all Gun methods (what users are used to)\n* Leaves user data unmodified, building upon a single timegraph property for that node.\n* Discover and traverse TimeGraphs very quickly with highly interconnected data due to decoupling.\n* Subset of special API methods for filtering and working with TimeGraphs. Can be built upon further.\n* Can be used in conjunction with other Date/Time libraries like [moment.js](http://momentjs.com)\n* Custom Date formatters/serializers (WIP) `dateFormatter` \u0026 `dateCompare`\n\n\u003cbr\u003e\n\n# Prerequisits:\n\n    var node = gun.get('list')\n\n\u003cbr\u003e\n\n# Initializer:\n\n    node.time(Optional startDate, Optional stopDate) \n    \nInitialize a TimeGraph in node chain for events such as `.get`, `.put`, `.on`, `.once`\n\n## Parameters: ##\n* `startDate` : Filters out data that came before `startDate`\n* `stopDate` : Filters out data that came after `stopDate`\n\n## Examples: ##\n* `node.time(startDate, stopDate)`\n* `node.time(startDate, null)`\n* `node.time(null, stopDate)`\n* `node.time(null, null)`\n\n\u003cbr\u003e\n\n# API Subset:\n* `node.time().first(number)` : Grab first `$num` items in TimeGraph\n* `node.time().last(number)` : Grab last `$num` items in TimeGraph\n* `node.time().filter(function(graphItem))` : Additional TimeGraph filtering if needed\n* `node.time().range` : Create a range for TimeGraph traversal. Uses the same semantics as `.time()`\n\n\u003cbr\u003e\n\n# Events:\n* `node.time().once` : Fires once for each piece of data in TimeGraph, filtering is done using timegraph methods\n* `node.time().on` : Fires continuosly for each piece of data in TimeGraph, filtering is done using timegraph methods\n* `node.time().time(callback)` : Subscribes to timegraph, returns `(data, key, time)`, where `data` is a node-ref.\n* `node.time().off` : Gun safety ;)\n\n\u003cbr\u003e\n\n# Range Events:\n* `range().once` : Same as `node.time().once`\n* `range().on` : Same as `node.time().on`\n* `range().time` : Same as `node.time().time(callback)`\n* `range().off` : Gun safety ;)\n\n\u003cbr\u003e\n\n# Graphing:\n* `node.time().get` : Retrieve data as normal with TimeGraph filtering if provided. Does not affect children nodes.\n* `node.time().put` : Put data into TimeGraph index using filter, if outside of bounds nothing is pushed into gun if `enforceData` is provided via opts.\n* `node.time().set` : Same as put\n* `node.time().time(data)` : Proxy/Shim for `.set` to provide a drop-in replacement for existing API.\n\n\u003cbr\u003e\n\n# TimeGraph Structure:\n    'dataNode': {\n       _: { '#': 'dataNodeSoul },\n       prop1: 'value',\n       prop2: 'value',\n    }\n\n    'timegraph/dataNodeSoul': {\n        first: { '#': 'timepoint/dataNodeSoul' },\n        last: { '#': 'timepoint/dataNodeSoul' },\n        soul: 'dataNodeSoul',\n        timepoint: { '#': 'timepoint/dataNodeSoul' },\n    }\n\n    'timepoint/dataNodeSoul': {\n        '2019': { '#': 'timepoint/dataNodeSoul:2019' },\n    }\n\n    'timepoint/dataNodeSoul:2019': {\n        '01': { '#': 'timepoint/dataNodeSoul:2019:01' }\n    }\n    \n    ...timepoint/etc\n    \n# Example TimeGraph Structures:\n## Code:\n    const app = gun.get('app')\n    const list = app.get('people').time()\n    list.set({ name: 'Levi' })\n    list.set({ name: 'Mark' })    \n\n## Structure:\n    { \n      jqg3tkqfEal1JtLWkn8V: { \n        _: { '#': 'jqg3tkqfEal1JtLWkn8V', ... },\n        name: 'Mark',\n      },\n\n      jqg3tkqrA9XCHBE1Vd7s: { \n        _: { '#': 'jqg3tkqrA9XCHBE1Vd7s', ... },\n        name: 'Levi',\n      },\n        \n      jqg3tkqn3HtZtCCrOucM: { \n        _: { '#': 'jqg3tkqn3HtZtCCrOucM', ... },\n        jqg3tkqfEal1JtLWkn8V: { '#': 'jqg3tkqfEal1JtLWkn8V' },\n        jqg3tkqrA9XCHBE1Vd7s: { '#': 'jqg3tkqrA9XCHBE1Vd7s' },\n      },\n\n      'timegraph/jqg3tkqn3HtZtCCrOucM': { \n        _: { '#': 'timegraph/jqg3tkqn3HtZtCCrOucM', ... },\n        first: { '#': 'timepoint/milli' },\n        last: { '#': 'timepoint/milli' },\n        soul: 'jqg3tkqn3HtZtCCrOucM',\n        timepoint: { '#': 'timepoint/jqg3tkqn3HtZtCCrOucM' },\n      },\n\n      ...timepoint/jqg3tkqn3HtZtCCrOucM:2019:...,\n        \n      'timepoint/jqg3tkqn3HtZtCCrOucM:2019:01:03:04:22:16:128': {\n        _: { '#': 'timepoint/jqg3tkqn3HtZtCCrOucM:2019:01:03:04:22:16:128', ... },\n        soul: 'jqg3tkqfEal1JtLWkn8V',\n      },\n\n      'timepoint/jqg3tkqn3HtZtCCrOucM:2019:01:03:04:22:16:132': { \n        _: { '#': 'timepoint/jqg3tkqn3HtZtCCrOucM:2019:01:03:04:22:16:132', ... },\n        soul: 'jqg3tkqrA9XCHBE1Vd7s', \n      },\n    }\n\n## Code:\n    // Primitives work too, although not sure how meaningful the data would be?\n    const app = gun.get('app').time()\n    app.get('personId').put(Math.floor(Math.random() * 11))  \n\n## Structure: (Out of date; has not been updated to reflect status)\n    { \n      app: { \n        _: { '#': 'app', '\u003e': { personId: 1545661692548, timegraph: 1545661692659.001 } },\n        personId: 6,\n        timegraph: { '#': 'timegraph/app' } \n      },\n      \n      'timegraph/app': { \n        _: { '#': 'timegraph/app', '\u003e': { personId: 1545661692658 } },\n        personId: 1545661692658 \n      },\n      \n      timegraphs: { \n        _: { '#': 'timegraphs', '\u003e': { 'timegraph/app': 1545661692660 } },\n        'timegraph/app': 'app' \n      } \n    }\n\n\u003cbr\u003e\n\n# Examples:\n## Insert data into TimeGraph\n\n    const app = gun.get('app')\n    const list = app.get('people').time()\n    list.set({ name: 'Levi' })\n    list.set({ name: 'Mark' })\n    \n## Retrieve data from TimeGraph\n\n    const app = gun.get('app')\n    app.get('people').time().map().once(console.log)\n\n## Insert valid data (inside of time bounds filter)\n\n    const app = gun.get('app')\n    const list = app.get('people').time(Date.now())\n    list.set({ name: 'Levi' })\n    list.set({ name: 'Mark' })\n\n## Insert invalid data (outside of time bounds filter)\n\n    var today = new Date()\n    var yesterday = new Date(today.setDate(today.getDate() - 1))\n    \n    const app = gun.get('app')\n    const list = app.get('people').time(null, yesterday)\n    list.set({ name: 'Levi' })\n    list.set({ name: 'Mark' })\n\n## Backward compatibility shim\n\n    app.get('people').get('timegraph').map().on((graphItem) =\u003e {\n      console.log(graphItem.soul) // Soul/key of item\n      console.log(graphItem.date) // Serializable UTC timestamp\n\n      // Retrieve new item\n      app.get('people').get(graphItem.soul).once(console.log)\n    })\n\n\u003cbr\u003e\n\n# TimePoint Structure:\n\n    'timepoint/soul': {\n      '2018': { // year\n        '12': { // month\n          '22': { // Day\n            '10': { // Hour\n              53: { // Min\n                05: { // Sec\n                  572: { // ms\n                    soul: dataNodeSoul\n                  }\n                }\n              },\n              54: { // Min\n                05: { // Sec\n                  572: { // ms\n                    soul: dataNodeSoul\n                  }\n                }\n              },\n            }\n          }\n        }\n      }\n    }\n\n## More examples coming soon\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbugs181%2Ftimegraph","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbugs181%2Ftimegraph","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbugs181%2Ftimegraph/lists"}