{"id":19620598,"url":"https://github.com/bas080/sendscript","last_synced_at":"2025-02-26T18:44:33.960Z","repository":{"id":194546735,"uuid":"691317529","full_name":"bas080/sendscript","owner":"bas080","description":"Write scripts in a JS DSL and run it on the server or somewhere else.","archived":false,"fork":false,"pushed_at":"2024-04-05T14:34:37.000Z","size":383,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-09T11:24:01.495Z","etag":null,"topics":["client-server","json","lisp","rpc"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/sendscript","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/bas080.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","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":"2023-09-14T00:03:25.000Z","updated_at":"2023-09-26T17:17:52.000Z","dependencies_parsed_at":"2024-01-26T18:25:47.078Z","dependency_job_id":"b7015433-c14c-4b44-988b-703b2cf5e597","html_url":"https://github.com/bas080/sendscript","commit_stats":null,"previous_names":["bas080/sendscript"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bas080%2Fsendscript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bas080%2Fsendscript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bas080%2Fsendscript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bas080%2Fsendscript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bas080","download_url":"https://codeload.github.com/bas080/sendscript/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240914824,"owners_count":19878050,"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":["client-server","json","lisp","rpc"],"created_at":"2024-11-11T11:19:23.528Z","updated_at":"2025-02-26T18:44:33.695Z","avatar_url":"https://github.com/bas080.png","language":"JavaScript","readme":"# SendScript\n\nWrite JS code that you can run on servers, browsers or other clients.\n\n[![NPM](https://img.shields.io/npm/v/sendscript?color=blue\u0026style=flat-square)](https://www.npmjs.com/package/sendscript)\n[![100% Code Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen?style=flat-square)](#tests)\n[![Standard Code Style](https://img.shields.io/badge/code_style-standard-brightgreen.svg?style=flat-square)](https://standardjs.com)\n[![License](https://img.shields.io/npm/l/sendscript?color=brightgreen\u0026style=flat-square)](./LICENSE.txt)\n\n\u003c!-- toc --\u003e\n\n- [Socket example](#socket-example)\n  * [Module](#module)\n  * [Server](#server)\n  * [Client](#client)\n- [Reference](#reference)\n  * [`sendscript/api.mjs`](#sendscriptapimjs)\n  * [`sendscript/exec.mjs`](#sendscriptexecmjs)\n- [TypeScript](#typescript)\n- [Tests](#tests)\n- [Formatting](#formatting)\n- [Changelog](#changelog)\n- [Dependencies](#dependencies)\n- [License](#license)\n\n\u003c!-- tocstop --\u003e\n\nSendScript leaves it up to you to choose HTTP, web-sockets or any other\nmethod of communication between servers and clients that best fits your\nneeds.\n\n## Socket example\n\nFor this example we'll use [socket.io][socket.io].\n\n```bash\nnpm install --no-save socket.io socket.io-client\n```\n\n\u003e We use the `--no-save` option because it's only for demonstration purposes.\n\n### Module\n\nWe write a simple module.\n\n```js\n// ./example/math.mjs\n\nexport const add = (a, b) =\u003e a + b\nexport const square = a =\u003e a * a\n```\n\n### Server\n\nHere a socket.io server that runs SendScript programs.\n\n```js\n// ./example/server.socket.io.mjs\n\nimport { Server } from 'socket.io'\nimport exec from '../exec.mjs'\nimport * as math from './math.mjs'\n\nconst server = new Server()\nconst port = process.env.PORT || 3000\n\nserver.on('connection', (socket) =\u003e {\n  socket.on('message', async (program, callback) =\u003e {\n    try {\n      const result = await exec(math, program)\n      callback(null, result) // Pass null as the first argument to indicate success\n    } catch (error) {\n      callback(error) // Pass the error to the callback\n    }\n  })\n})\n\nserver.listen(port)\nprocess.title = 'sendscript'\n```\n\n### Client\n\nNow for a client that sends a program to the server.\n\n```js\n// ./example/client.socket.io.mjs\n\nimport socketClient from 'socket.io-client'\nimport api from '../api.mjs'\n\nconst port = process.env.PORT || 3000\nconst client = socketClient(`http://localhost:${port}`)\n\nconst exec = program =\u003e {\n  return new Promise((resolve, reject) =\u003e {\n    client.emit('message', program, (error, result) =\u003e {\n      error\n        ? reject(error)\n        : resolve(result)\n    })\n  })\n}\n\nconst { add, square } = api(['add', 'square'], exec)\n\nconsole.log(\n  await square(add(1, add(add(2, 3), 4)))\n)\n\nprocess.exit(0)\n```\n\nNow we run this server and a client script.\n\n```bash\n# Run the server\nnode ./example/server.socket.io.mjs\u0026\n\n# Run the client example\nnode ./example/client.socket.io.mjs\n\npkill sendscript\n```\n```\n100\n```\n\n## Reference\n\nSendScript is essentially a way to serialize a program to then send over the\nwire and execute it somewhere else.\n\nWe only have two modules. One that helps you write programs that can be sent\nover the wire and another for running that program.\n\n### `sendscript/api.mjs`\n\nThe api module exports a function that takes two arguments.\n\n1. The schema, which represents the values that are available.\n2. The function that will be called with the serializable version of the\n   program.\n\nIt returns an object that contains functions which are defined in the schema.\nThese functions are a JavaScript API for writing programs that can be sent to\na server.\n\n```js\nimport api from './api.mjs'\n\nconst  { add, subtract } = api(\n  ['add', 'subtract'],\n  serializableProgram =\u003e sendSomewhereToBeExecuted(serializableProgram)\n)\n\nawait add(1, 2) // =\u003e 3\nawait subtract(1, 2) // =\u003e -1\nawait add(1, subtract(2, 3)) // =\u003e 0\n```\n\nThe add and subtract functions are thennable. The execute function is called as\nsoon as await or `.then` is used.\n\n\u003e Notice that you do not have to await the subtract call. You only need to\n\u003e await when you want to execute the program.\n\nThis API is composable and wrappable.\n\n### `sendscript/exec.mjs`\n\nThe exec function takes an environment object and any valid SendScript program.\n\n```js\nimport exec from './exec.mjs'\n\nexec({\n  add: (a, b) =\u003e a + b,\n  subtract: (a, b) =\u003e a - b\n}, ['add', 1, [subtract, 1, 2]])\n```\n\nThe array you see here is the LISP that SendScript uses to represent programs.\n\nYou could use SendScript without knowing the details of how the LISP works. It\nis an implementation detail and might change over time.\n\n## TypeScript\n\nThere is a good use-case to write an environment module in TypeScript.\n\n1. Obviously the module would have the benefits that TypeScript offers when\n   coding.\n2. You can use tools like [typedoc][typedoc] to generate docs from your types to\n   share with consumers of your API.\n3. You can use the types of the module to coerce your client to adopt the\n   modules type.\n\n```bash\n# Create pretty docs for your module.\nnpx typedoc my-module.ts\n```\n\nNow we can use the `my-module.ts` file for the client API.\n\n```ts\nimport type * as MyModule from './my-module'\n\nimport sendScriptApi from 'sendscript/api.mjs'\n\nexport default sendScriptApi([\n  fnOne,\n  fnTwo,\n], /* perform websocket request */) as typeof MyModule\n```\n\n\u003e [!NOTE]\n\u003e Although type coercion on the client side can improve the development\n\u003e experience, it does not represent the actual type.\n\u003e Values are likely subject to serialization and deserialization,\n\u003e particularly when interfacing with JSON formats.\n\n## Tests\n\nTests with 100% code coverage.\n\n```bash\nnpm t -- -R silent\nnpm t -- report text-summary\n```\n```\n\n\u003e sendscript@0.1.4 test\n\u003e tap -R silent\n\n\n\u003e sendscript@0.1.4 test\n\u003e tap report text-summary\n\n\n=============================== Coverage summary ===============================\nStatements   : 100% ( 110/110 )\nBranches     : 100% ( 32/32 )\nFunctions    : 100% ( 10/10 )\nLines        : 100% ( 110/110 )\n================================================================================\n```\n\n## Formatting\n\nStandard because no config.\n\n```bash\nnpx standard\n```\n\n## Changelog\n\nThe [changelog][changelog] is generated using the useful\n[auto-changelog][auto-changelog] project.\n\n```bash\nnpx auto-changelog -p\n```\n\n## Dependencies\n\nCheck if packages are up to date on release.\n\n```bash\nnpm outdated \u0026\u0026 echo 'No outdated packages found'\n```\n```\nNo outdated packages found\n```\n\n## License\n\nSee the [LICENSE.txt][license] file for details.\n\n[license]:./LICENSE.txt\n[socket.io]:https://socket.io/\n[changelog]:./CHANGELOG.md\n[auto-changelog]:https://www.npmjs.com/package/auto-changelog\n[typedoc]:https://github.com/TypeStrong/typedoc\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbas080%2Fsendscript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbas080%2Fsendscript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbas080%2Fsendscript/lists"}