{"id":18901112,"url":"https://github.com/regular/ssb-sandboxed-views","last_synced_at":"2026-03-03T19:30:19.093Z","repository":{"id":57368805,"uuid":"269098941","full_name":"regular/ssb-sandboxed-views","owner":"regular","description":null,"archived":false,"fork":false,"pushed_at":"2020-06-23T11:29:24.000Z","size":29,"stargazers_count":1,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-12-31T09:46:02.669Z","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":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/regular.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":"2020-06-03T13:42:43.000Z","updated_at":"2020-08-19T04:45:46.000Z","dependencies_parsed_at":"2022-08-23T19:30:23.535Z","dependency_job_id":null,"html_url":"https://github.com/regular/ssb-sandboxed-views","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/regular%2Fssb-sandboxed-views","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/regular%2Fssb-sandboxed-views/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/regular%2Fssb-sandboxed-views/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/regular%2Fssb-sandboxed-views/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/regular","download_url":"https://codeload.github.com/regular/ssb-sandboxed-views/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239886024,"owners_count":19713414,"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":[],"created_at":"2024-11-08T08:55:12.958Z","updated_at":"2026-03-03T19:30:16.977Z","avatar_url":"https://github.com/regular.png","language":"JavaScript","readme":"ssb-sandboxed-views\n---\nThis plug-in for ssb-server enables applications to build and query the database indexes they need, without requiring further plug-ins. The goal is for a single instance of ssb-server to serve many different applications with different database views. A view (= indexing function) can be added dynamically. The function then runs in an isolated JS context (quickjs) in a worker thread of ssb-server. The resulting index is identical to the ones created by ssb-review-level/flumeview-level and can be queried in a similar fashion.\n\n``` js\nssb.sandviews.openView(`\n  module.exports = function(kvm) {\n    const {key, value, meta, seq} = kvm\n    const {content} = value\n\n    // if encrypted, content is a string\n    if (content.type == undefined) return [] \n    return [content.type]\n  }\n`, (err, handle) =\u003e {\n  pull(\n    sandviews.read(handle, {values: false}),\n    pull.log()\n  )\n})\n```\n\n## Known issues/status\n\nThis is experimental and some parts are not implemented yet.\n\n- currently requires ssb-revisions and exclusively creats views that support mutations\n- lifetime of leveldb is not managed yet. (databases are created and never deleted)\n- no protection agains endless loops in map functions yet\n\n## How it works\n\nAn application calls ssb.sandviews.openView() with the _source code_ of a commonJS module that exports the map function. The map function is called whenever a message is added to the flumelog or, in case ssb-revisions is present in the ssb-server stack of plugins, when a messages is mutated. The map functions output is then written to a leveldb database. \n\n### Versioning\n\nInstead of relying on manual version number bumping like in flumeview-level and ssb-revisions, ssb-sandboxed-views creates a _code fingerprint_ of the application-provided function. If the fingerprint changes, a new index will be build and the old one will eventually by purged if no application has used it for a while (not implemented). The idea of a _code fingerprint_ is that it does not change if the source code changes are trivial and don't affect the output. Changes in formatting, comments, variable and function names, braces around single-statement if-blocks, etc, will not change the fingerprint.\n\nApplications that provide map functions with identical fingerprints will automatically share the index.\n\n### Security\n\nFor security reasons, the code provided by the application does not run in NodeJS directly, instead an instance of sandbox-worker is created, so that the code runs in an isolated JS runtime implemented by quickjs with no access to any NodeJS module. This ensure that the application-provided code cannot interact with the host system or the network. To protect against endless loops, the quickjs runtime runs in a worker thread. (no timeout is implemented yet though)\n\n## API\n\n### `openView(code[, opts], cb)`\n\ninstanciates a view with the given `source code`. If the view does not exist, it will be created.\n\n  - `code` source code of a commonJS module that exports a single function, the map function (see below)\n  - `opts` options object\n    - `bufferSize` number of messages to buffer before sending to worker thrad. Defaults to 200.\n    - `warnings` if set to an empty array (or any other object with a `push` property), will receive warnings issued by terser, for example if dead code was deleted.\n\n  - `cb` is called with `err` and `handle`\n    - `handle` is the view's handle/id. It is used in the remaining functions of the API.\n\n### `get(handle, key, cb)`\n\nget a single index entry.\n\n  - `handle` as created by openView\n  - `key` as returned by the map function\n\n### `read(handle[, opts])`\n\nQuery a sandboxed view.\n\n  - `handle` as created by openView\n  - `opts` same as in flumeview-level\n\nreturns a pull-stream source\n\nLicense: MIT\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fregular%2Fssb-sandboxed-views","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fregular%2Fssb-sandboxed-views","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fregular%2Fssb-sandboxed-views/lists"}