{"id":18169894,"url":"https://github.com/karfau/runex","last_synced_at":"2025-04-01T13:33:30.065Z","repository":{"id":36741991,"uuid":"229339271","full_name":"karfau/runex","owner":"karfau","description":"Run (javascript) module export as a script","archived":false,"fork":false,"pushed_at":"2023-10-02T21:57:00.000Z","size":703,"stargazers_count":1,"open_issues_count":6,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-27T22:38:07.621Z","etag":null,"topics":["cli","javascript","nodejs","script"],"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/karfau.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}},"created_at":"2019-12-20T21:31:13.000Z","updated_at":"2024-01-12T18:11:28.000Z","dependencies_parsed_at":"2023-02-18T09:01:15.870Z","dependency_job_id":null,"html_url":"https://github.com/karfau/runex","commit_stats":{"total_commits":163,"total_committers":4,"mean_commits":40.75,"dds":0.6196319018404908,"last_synced_commit":"9d218d848a2d94d8d812efb5e8a28448e6fba8da"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karfau%2Frunex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karfau%2Frunex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karfau%2Frunex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karfau%2Frunex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/karfau","download_url":"https://codeload.github.com/karfau/runex/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":222376250,"owners_count":16974312,"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":["cli","javascript","nodejs","script"],"created_at":"2024-11-02T15:00:24.778Z","updated_at":"2024-11-02T15:01:29.326Z","avatar_url":"https://github.com/karfau.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![npm](https://img.shields.io/npm/v/runex)](https://www.npmjs.com/package/runex)\n[![dependencies status](https://david-dm.org/karfau/runex.svg)](https://david-dm.org/karfau/runex)\n[![codecov - `tap --100` is part of CI](https://codecov.io/gh/karfau/runex/branch/master/graph/badge.svg)](https://codecov.io/gh/karfau/runex)\n\n# runex\n\nRun module export as a `node` or `npx` script.\n\n(See [Why not ...](#why-not-) for alternative approaches.)\n\n## When to use\n\nSo you have some code that you want to be able to run from the command line.\nYou can of course just write it down into a file and run it with `node ./script.js`.\nMaybe you go one more step and add a [hashbang](https://en.wikipedia.org/wiki/Hashbang) and make it executable,\nso on a linux shell you run it with just `./script.js`.\nBut this way you can not import the file without executing all the code.\nWrapping all the code into a function and executing it `if (require.main === module)` helps with that.\nYou also manage to parse those arguments you need, maybe using one of the available libraries.\n\n- Are you able to also call your function from code with those arguments? \n- Do you need to make any async call (like making a request to an API)?\n- What about error handling: `try {...} catch (err) {...}` or `.then(...).catch(...)`?\n- Do you have/need one script or many scripts?\n\nDon't regret, `runex` was created, because this was just to much time and code \nfor something that convenient.\n\n## Goals\n\n1. reduce the amount of code that needs to be written to run a module (a javascript file) as a node script\n2. the module does not (need to) have any special code to make it executable,\nincluding support for `async` functions/promises\n3. convention over configuration\n\n## How to take advantage\n\nAs soon as your module exports a method with the name `run`, it is \"runnable\":\n\n```\nUsage: [npx] runex [options] runnable [args]\n\nOptions:\n  -r, --require \u003cmodule\u003e  0..n modules for node to require (default: [])\n  -h, --help              output usage information\n```\n\n- it receives (just the relevant) arguments (as strings)\n- it can be `async` / return a `Promise`\n- it can throw (rejected Promises will be treated the same way)\n- it is in control of `stdout` (`runex` only communicates over `stderr`), with one exception:\n  - if you return a value it will be printed to `stdout` (so you don't have to, see goal)\n    if `typeof value === 'object` it will be `JSON.stringify`ed.\n\nGo check some [examples](https://github.com/karfau/runex/tree/master/examples).\n\n### But I want my module to be executable\n\nOf course your can make use of `runex` to make your module \"executable\"\n```javascript\nif (require.main === module) {\n  require('runex').run(module);\n}\n```\nThe above code would make the following differences:\n- users of your module can write `node [path/to/]module` instead of `node runex [path/to/]module`\n- you are able to customize option parsing\n\n## Why not ...\n\n- \u003chttps://github.com/DVLP/run-func\u003e:  \nThis library was my initial inspiration when searching for an existing solution. \nBut I think not every function is easy to run as a script\n(just think about the type of the arguments, return types, etc.). \nSo I decided to rely on a naming convention for the executable function.\n\n\n- `if (require.main === module) {...}`:  \nThe \"native\" way of making a module \"executable\".  \nBut the tricky part is what needs to be written instead of `...`, in **every** \"executable\" module.  \nThat's why I listed the first [first goal](#goals).  \n\nBTW: `runex` makes use of this mechanism, so you don't need to, [but you can of course have both](#but-i-want-my-module-to-be-executable).\n\nDo you know an alternative that should be listed? Create an issue or PR!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarfau%2Frunex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkarfau%2Frunex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarfau%2Frunex/lists"}