{"id":19352805,"url":"https://github.com/thisconnect/planet","last_synced_at":"2025-04-23T07:31:24.203Z","repository":{"id":57325532,"uuid":"1929256","full_name":"thisconnect/planet","owner":"thisconnect","description":"Collaboratively edit and synchronize JSON-style data with Node.js","archived":false,"fork":false,"pushed_at":"2020-03-13T01:17:01.000Z","size":522,"stargazers_count":9,"open_issues_count":7,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-02T10:05:36.736Z","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/thisconnect.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":"2011-06-21T13:27:51.000Z","updated_at":"2017-08-02T17:16:23.000Z","dependencies_parsed_at":"2022-09-09T08:52:13.882Z","dependency_job_id":null,"html_url":"https://github.com/thisconnect/planet","commit_stats":null,"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thisconnect%2Fplanet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thisconnect%2Fplanet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thisconnect%2Fplanet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thisconnect%2Fplanet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thisconnect","download_url":"https://codeload.github.com/thisconnect/planet/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250391247,"owners_count":21422863,"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-10T04:40:31.724Z","updated_at":"2025-04-23T07:31:23.413Z","avatar_url":"https://github.com/thisconnect.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Planet\n\nCollaboratively edit JSON-style data in realtime using \n[Socket.IO](https://github.com/LearnBoost/socket.io) by\nsynchronizing all operations on a planetary shared object.\nEach operation will be received in exactly the same\norder as they are incoming to the Planet server. \nThis includes the client that is emitting the operation.\nThis approach guarantees the exact same state on all clients\nand has been proven to work reliably in other projects such as\n[netpd](http://www.netpd.org/).\n\nPlanet is optimized to edit JSON style data and does not require\n[OT](http://en.wikipedia.org/wiki/Operational_transformation).\nIf you are looking for rich text editing have a look at \n[ShareJS](https://github.com/josephg/ShareJS).\n\n\n\nExample\n-------\n\n### Server\n\n```javascript\nvar planet = require('planet'),\n\tsocket = require('socket.io').listen(8080);\n\nplanet(socket);\n```\n\n### CLI\n\n```bash\nplanet --host localhost --port 8080\n```\n\n\n### Client\n\n```javascript\nio.connect('//:8080')\n.on('connect', function(){\n\tthis.emit('merge', {\n\t\t'sugar': 1,\n\t\t'milk': 0\n\t});\n\n\tthis.on('set', function(key, value){\n\t\tconsole.log(key, value);\n\t\t// sugar 2\n\t\t// milk 100\n\t});\n\n\tthis.emit('set', 'sugar', 2);\n\tthis.emit('set', 'milk', 100);\n\n\tthis.emit('get', function(data){\n\t\tconsole.log(data);\n\t\t// {'sugar': 2, 'milk': 100}\n\t});\n});\n```\n\n\n\nOr run the example with:\n\n```bash\nnode test/example\n```\n\n\n### Operations\n\n  - `set` - Sets a value at a specific location.\n    The value will be overwritten, not merged!\n\n  - `remove` - Deletes a value at a specified location.\n\n  - `merge` - Recursively merges data into the state.\n\n  - `delete` - Deletes the state.\n\n  - `get` - Asynchronously fetches values from the state,\n    optionally at a specified location. Returns the whole\n\tstate if no location is passed.\n\n\n\n### Terminology\n\n  - `operation` - The custom events that is used to\n    modify the planetary shared object.\n\n  - `value` - Can be of type string, number, object,\n    array, boolean or null.\n\n  - `location` - Specifies a property of the shared object\n    by a key (string) or path (array).\n\n  - `path` - A path is an array of strings or/and numbers\n    to specify a property in an object. Numbers refer to\n\telement positions of arrays.\n\n  - `data` - Refers always to an object.\n\n  - `state` - The current content of the planet\n    that can be manipulated by the operations or\n\tread with `get`.\n\n\n\n### Arrays\n\nArrays are not treated as objects and will not be merged\nby `merge` operations. The elements of an array can be\n`set` or fetched by `get` opernations. Removing single\nelements from an array is not yet specified.\n\n\n\n### String\n\nSingle characters of a string value can be manipulated\nwith `set` or read with `get`.\n\n\n\nInstall\n-------\n\n```bash\nnpm install planet\n```\n\n\nInclude the Client\n------------------\n\n\n\n```html\n\u003cscript src=\"//localhost:8080/socket.io/socket.io.js\"\u003e\u003c/script\u003e\n```\n\n\n\n```js\n// or within Node.js \nvar io = require('socket.io-client');\n```\n\n\n\nEvents\n------\n\nPlanet Operations are fired as Socket.IO custom events.\nThe operations can be listened on both the server and the client\nvia `on` and `once`.\n\n\n\n### Event: set\n\n```js\nclient.on('set', function(location, value){ });\n```\n\n\n\n### Event: remove\n\n```js\nclient.on('remove', function(location){ });\n```\n\n\n\n### Event: merge\n\n```js\nclient.on('merge', function(data){ });\n```\n\n\n\n### Event: delete\n\n```js\nclient.on('delete', function(){ });\n```\n\n\n\nClient API\n----------\n\n\n\n### Method: connect\n\n```js\nvar earth = io.connect('//:8004', options);\n```\n\n\n\n### Method: disconnect\n\n```js\nearth.disconnect();\n```\n\n\n\n### Method: emit\n\nEmits Planet operations.\n\n\n\n### Emit: set\n\n```js\nearth.emit('set', 'bag', null); // {'bag': null}\nearth.emit('set', 'bag', {'sugar': 20}); // {'bag': {'sugar': 20}}\nearth.emit('set', ['bag', 'eggs'], 12); // {'bag': {'sugar': 20, 'eggs': 12}}\nearth.emit('set', ['todo-list', 0], 'My first thing todo');\n```\n\n\n\n### Emit: remove\n\n```js\nearth.emit('remove', 'key');\nearth.emit('remove', ['bag', 'eggs']);\n```\n\n\n\n### Emit: merge\n\n```js\nearth.emit('merge', {'bag': {'eggs': 6, 'milk': 100}});\nearth.emit('merge', {'bag': {'sugar': 20}});\n```\n\n\n\n### Emit: delete\n\n```js\nearth.emit('delete');\n```\n\n\n\n### Emit: get\n\n```js\nearth.emit('get', function(data){ });\nearth.emit('get', 'bag', function(value){ });\nearth.emit('get', ['bag', 'eggs'], function(value){ });\nearth.emit('get', ['todo-list', 0], function(value){ });\n```\n\n\n\nServer API\n----------\n\n```js\nvar Planet = require('planet'),\n\tsocket = require('socket.io').listen(8080, 'localhost');\n```\n\n\n\n### Constructor: Planet\n\n```js\nvar earth = new Planet(socket, options);\n```\n\nThe `new` keyword is optional.\n\n##### Arguments\n\n1. Socket - Socket.IO socket server.\n2. Options (object) - the configuration object.\n\n##### Options\n\n  - `limit` - the maximum amount of concurrent client connections.\n  Defaults to 200.\n\n\n\n### Method: merge\n\n```js\nearth.merge({'key': 'value'});\n```\n\n\n\n### Method: set\n\n```js\nearth.set('bag', {'sugar': 20});\nearth.set(['bag', 'eggs'], 12);\nearth.set(['todo-list', 0], 'My first thing todo');\n```\n\n\n\n### Method: remove\n\n```js\nearth.remove('key');\nearth.remove(['bag', 'eggs']);\n```\n\n\n\n### Method: delete\n\n```js\nearth.delete();\n```\n\n\n\n### Method: get\n\n```js\nearth.get(function(data){ });\nearth.get('bag', function(value){ });\nearth.get(['bag', 'eggs'], function(value){ });\nearth.get(['todo-list', 0], function(value){ });\n```\n\n\n\nCLI API\n-------\n\nTo run `planet` form a command-line interface install\nPlanet globally `npm install planet -g`\nor `cd bin \u0026\u0026 ./planet`.\n\n\n\n### CLI Options\n\n  - `-p`, `--port [NUMBER]` - The port to bind to (default: 8004).\n\n  - `-h`, `--host [STRING]` - The host to connect to (default: 127.0.0.1).\n\n  - `-l`,  `--limit [NUMBER]` - Maximum concurrent client connections,\n    a number lower than your ulimit (default: 200).\n\n  - `--io.\u003cconfiguration\u003e` - \n  [Socket.IO configuration](https://github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO)\n  for example:\n    `--io.transports=websocket,htmlfile`\n    `--no-io.browser-client-cache`\n  Note the dot notation and that dashes after --io. will \n  be replaced by whitespace to match Socket.IO configs.\n\n  - `-v`, `--version` - Prints the current version.\n\n  - `--help` - Shows this help message.\n\n\n\nTests\n-----\n\n```make\n#test server api\nmake test-server\n\n#test client api\nmake test-client\n\n#build browser test\nmake test-browser\n\n#run test server\nnode test/server\n```\n\n\n\nBenchmarks\n----------\n\n```bash\nnode test/benchmark\n```\n\n\n\nTODO\n----\n\n- Strict (option for disallowing auto-creation of setting keys at new location)\n- Predefined model (option for predefining a data structure \n  and disalow merging/setting inexistent keys)\n- Latency optimization\n- Cleanup error messages\n- Eventually provide a client side script for merge, get and set manipulation\n\n\n\n#### Dependencies\n\n- [Socket.IO](http://socket.io/)\n- [Yargs](https://npmjs.org/package/yargs)\n- [Tool](https://github.com/thisconnect/tool)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthisconnect%2Fplanet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthisconnect%2Fplanet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthisconnect%2Fplanet/lists"}