{"id":13555595,"url":"https://github.com/dominictarr/level-scuttlebutt","last_synced_at":"2025-12-30T03:04:58.305Z","repository":{"id":5703512,"uuid":"6914176","full_name":"dominictarr/level-scuttlebutt","owner":"dominictarr","description":"leveldb persistence for scuttlebutts (scuttlebutt/crdt/append-only and friends)","archived":false,"fork":false,"pushed_at":"2014-09-11T08:22:29.000Z","size":365,"stargazers_count":25,"open_issues_count":5,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-08-15T10:25:36.009Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/dominictarr.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}},"created_at":"2012-11-29T02:53:05.000Z","updated_at":"2024-03-15T22:53:55.000Z","dependencies_parsed_at":"2022-08-24T21:02:23.665Z","dependency_job_id":null,"html_url":"https://github.com/dominictarr/level-scuttlebutt","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dominictarr/level-scuttlebutt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominictarr%2Flevel-scuttlebutt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominictarr%2Flevel-scuttlebutt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominictarr%2Flevel-scuttlebutt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominictarr%2Flevel-scuttlebutt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dominictarr","download_url":"https://codeload.github.com/dominictarr/level-scuttlebutt/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominictarr%2Flevel-scuttlebutt/sbom","scorecard":{"id":350850,"data":{"date":"2025-08-11","repo":{"name":"github.com/dominictarr/level-scuttlebutt","commit":"fe0f9b68579b391e6995a5ca250ebc54a7fa93a3"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.2,"checks":[{"name":"Code-Review","score":1,"reason":"Found 3/30 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 3 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T08:16:07.060Z","repository_id":5703512,"created_at":"2025-08-18T08:16:07.060Z","updated_at":"2025-08-18T08:16:07.060Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276280410,"owners_count":25615601,"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-09-21T02:00:07.055Z","response_time":72,"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-08-01T12:03:18.210Z","updated_at":"2025-09-26T06:30:23.279Z","avatar_url":"https://github.com/dominictarr.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","others"],"sub_categories":[],"readme":"# level-scuttlebutt\n\nPlugin to add persistence and querying [scuttlebutt](https://github.com/scuttlebutt) documents\nstored in leveldb.\n\nInstead of representing an object as a single document, scuttlebutt represents a document as\na series of immutable transactions. The 'document' is modified by appending a new transaction.\nOld transactions that are no longer relevant can be cleaned up, but you can never modify a\ntransaction in place. As it turns out, leveldb (a log-structured merge tree) is optimized for \nexactly this sort of data.\n\nMust be used with [level-sublevel](https://github.com/dominictarr/level-sublevel)\n\n# Example\n\n``` js\nvar levelup = require(\"levelup\")\nvar level_scuttlebutt = require(\"level-scuttlebutt\")\nvar SubLevel = require('level-sublevel')\n\n\n//create a leveldb instance...\n//levelup must be extended with SubLevel!\nvar db = SubLevel(levelup(DB_FILE))\n\n\n\n//a scuttlebutt model.\nvar Model = require('scuttlebutt/model')\n\n//level-scuttlebutt needs to have an unique identifier of the current instance\nvar udid = require('udid')('app-name')\n\n\n//patch it with level-scuttlebutt.\nvar sbDb = db.sublevel('scuttlebutt') //add a scuttlebutt 'table'\n\n//k\nlevel_scuttlebutt(sbDb, udid, function (name) {\n  //create a scuttlebutt instance given a name.\n  //the key will match the start of the name.\n  return new Model()\n  //now is a good time to customize the scuttlebutt instance.\n})\n\n//open a scuttlebutt instance by name.\nsbDb.open(name, function (err, model) {\n  model.on('change:key', console.log) //...\n  model.set('key', value)\n  \n  // when you're done get rid of it\n  model.dispose()\n})\n\n//the toJSON values are stored in the db,\n//so you can just use any other map reduce library on it!\nsbDb.views['all'] =\n  mapReduce(sbDb, 'all', \n    function (key, json, emit) { \n      return emit(key.split('!'), 1)\n    },\n    function (acc, item) {\n      return '' + (Number(acc) + Number(item))\n    },\n    '0'\n  )\n\n```\n\n## Initialization\n\nAdd `level-scuttlebutt` plugin to the `db` object\n`var level_scuttlebutt = require('level-scuttlebutt'); level_scuttlebutt(db, ID, schema)`\n\n`ID` is a unique string that identifies the node (the machine) and should be \ntied to the leveldb instance.\nI suggest using [udid](https://github.com/dominictarr/udid).\n\n`schema` should be a function that takes a string (the name of the scuttlebutt instance)\nand returns and empty scuttlebutt instance.\nYou can use [scuttlebutt-schema](https://github.com/dominictarr/scuttlebutt-schema).\n\n## Queries\n\nUse some other `level-*` plugin for queries!\n\n[map-reduce](https://github.com/dominictarr/map-reduce), \n[level-map-merge](https://github.com/dominictarr/level-map-merge)\n\n### Example\n\nget the 10 last edited documents!\n\n``` js\nsbDb.views['latest10']\n  = \n  MapReduce(sdb, 'latest10',\n  function (key, json) {\n    var name = key\n    var obj = JSON.parse(json)\n    //emit 0-many group-value pairs.\n    //value must be a string or a buffer.\n    this.emit([], JSON.stringify({name: name, time: Date.now(), length: obj.text.length}))\n  },\n  //merge the latest value into the accumulator.\n  function (acc, value) {\n    var all = JSON.parse(acc).concat(JSON.parse(value))\n    //sort by time, decending.\n    all.sort(function (a, b) {\n      return b.time - a.time\n    })\n    //top ten most recent\n    var all = all.slice(0, 10)\n    return JSON.stringify(all)\n  },\n  //the first value for the accumulator.\n  //since we are parsing it, it needs to be valid JSON.\n  '[]'\n})\n```\n\n\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdominictarr%2Flevel-scuttlebutt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdominictarr%2Flevel-scuttlebutt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdominictarr%2Flevel-scuttlebutt/lists"}