{"id":13452581,"url":"https://github.com/gaui/argster","last_synced_at":"2026-01-21T20:46:59.574Z","repository":{"id":32940518,"uuid":"144494364","full_name":"gaui/argster","owner":"gaui","description":"Just a simple command/argument manager","archived":false,"fork":false,"pushed_at":"2025-06-19T16:52:42.000Z","size":1093,"stargazers_count":7,"open_issues_count":2,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-24T23:38:00.261Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","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/gaui.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"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,"zenodo":null}},"created_at":"2018-08-12T19:18:49.000Z","updated_at":"2025-06-19T16:52:46.000Z","dependencies_parsed_at":"2024-01-16T03:46:25.435Z","dependency_job_id":"935807fa-bcaa-4f7f-9e84-8c59cbdb8b14","html_url":"https://github.com/gaui/argster","commit_stats":{"total_commits":230,"total_committers":3,"mean_commits":76.66666666666667,"dds":0.4869565217391304,"last_synced_commit":"8294d862894275b7cd02c1a5e316611435445844"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/gaui/argster","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaui%2Fargster","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaui%2Fargster/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaui%2Fargster/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaui%2Fargster/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gaui","download_url":"https://codeload.github.com/gaui/argster/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaui%2Fargster/sbom","scorecard":{"id":419663,"data":{"date":"2025-08-11","repo":{"name":"github.com/gaui/argster","commit":"b30155974d94c56e34cd3db0ebbe4c49f1984ad8"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.7,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/14 approved changesets -- score normalized to 0","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":"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":"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":"Maintained","score":10,"reason":"21 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"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":"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":"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":"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":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"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 30 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"}},{"name":"Vulnerabilities","score":8,"reason":"2 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-xffm-g5w8-qvg7","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T00:51:36.496Z","repository_id":32940518,"created_at":"2025-08-19T00:51:36.496Z","updated_at":"2025-08-19T00:51:36.496Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28642337,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T18:04:35.752Z","status":"ssl_error","status_checked_at":"2026-01-21T18:03:55.054Z","response_time":86,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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-07-31T07:01:28.135Z","updated_at":"2026-01-21T20:46:59.567Z","avatar_url":"https://github.com/gaui.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# argster\n\nA simple command/argument manager with a simple API that makes it easy to build dynamic commands and dynamic arguments with computed values.\n\n## What\n\nThe [Builder's](#builder) builds and manages commands. When a new `Builder` instance is created, it provides a simple API to create and execute commands, append and prepend dynamic arguments.\n\nWhen creating [commands](#command) through the builder, it goes through the list of file patterns recursively, reads each file, parses each line in the file, resolves dynamic variables to their values, and generates an executable command string. When a command is executed, it returns an object which contains both a _promise_ which is resolved or rejected based on how the process exits (0 / 1), along with a [Readable](https://nodejs.org/api/stream.html#stream_readable_streams) streams object for listening to stdout and stderr streams.\n\nSo instead of manually creating the following command in our CI pipeline, with dynamic arguments and dynamic values that need to be computed at runtime:\n\n```bash\ndocker build . -t myimage:1.0.0 --label org.label-schema.build-date=2019-07-14 --label org.label-schema.name=argster-120-example --label org.label-schema.vendor=Vendor --label org.label-schema.version=1.0.0 --label org.label-schema.schema-version=1.0.0-rc.1\n```\n\nYou could create a simple JavaScript script and create complex commands with dynamic arguments (evaluated JavaScript functions) and version control it all with Git.\n\n### Example (docker build)\n\nPay special attention to the `org.label-schema.build-date` label with the dynamic date.\n\n**1. If we created the following builder and command**\n\n```typescript\nconst options = {\n  dynamicVariables: {\n    BUILD_DATE: () =\u003e new Date().toISOString().slice(0, 10),\n    NAME: () =\u003e pkg.name,\n    VERSION: () =\u003e pkg.version,\n    DESCRIPTION: () =\u003e pkg.description,\n    VENDOR: () =\u003e \"Vendor\",\n    SCHEMA_VERSION: () =\u003e \"1.0.0-rc.1\"\n  },\n  skipUnresolvedVariables: true\n};\n\nconst builder = new Builder(options);\n\nconst cmd = builder.createCommand('docker build .', [\n  {\n    patterns: ['**/*.lbl'],\n    prefix: '--label'\n  }\n]);\n\ncmd.prependArgument({\n  argument: `myimage:${pkg.version}`,\n  prefix: '-t'\n});\n\ncmd.exec();\n```\n\n**2. And had this pattern file**\n\n**`./some/deep/path/file.lbl`**\n\n```ini\norg.label-schema.build-date=${BUILD_DATE}\norg.label-schema.name=${NAME}\norg.label-schema.description=${DESCRIPTION}\norg.label-schema.vendor=${VENDOR}\norg.label-schema.version=${VERSION}\norg.label-schema.schema-version=${SCHEMA_VERSION}\n```\n\n**3. This will be the executed command:**\n\n```bash\ndocker build . -t myimage:1.0.0 --label org.label-schema.build-date=2019-07-14 --label org.label-schema.name=argster-120-example --label org.label-schema.vendor=Vendor --label org.label-schema.version=1.0.0 --label org.label-schema.schema-version=1.0.0-rc.1\n```\n\n## Why\n\nI always felt the lack of a tool/library to easily create dynamic commands with dynamic arguments that were derived by functions but had the possibility to version control, without creating complex shell scripts. It first started when I was experimenting with DevOps and started to work with Docker trying to create sane images. I started reading about best practices around labeling and tagging Docker images and stumbled up on [Label Schema](http://label-schema.org/rc1/#label-semantics).\n\nI sat down and thought about the following technologies:\n\n- Label Schema and label semantics for e.g. Docker images\n- Dockerfile and `ENV` / `ARG`\n- Dockerfile and `.env` file\n- Power of JavaScript\n- Power of variables\n- Power of Git\n\nWith the great tech above I wanted to utilise it all and create a Node library that was able to build up complex dynamic command-line commands and arguments. Then the idea of **argster** was born.\n\nCheck out this [CodeSandbox](https://codesandbox.io/s/lyjjqzv38q) for examples.\n\nCheckout the [roadmap](#roadmap) for what to come.\n\n## Setup\n\nYou can install the npm package with npm:\n\n```bash\nnpm install argster\n```\n\n## Concepts\n\n### Builder\n\nA builder is a core component that builds and manages commands.\nThe builder accepts [options](#options) to adjust how command arguments are parsed, etc.\n\n### Command\n\nA command is a string that is executed as a process. It contains a base command and arguments that can be assembled and manipulated.\nWhen a command is created, it accepts file patterns as arguments, that are then processed, evaluated and converted to\na finalized command string, which is then executed.\n\n#### File patterns\n\nFile patterns are structures that contain a prefix and a list of file patterns, where each file matching the pattern is\nread and each line assembled into a command string, which is then executed.\n\n**Example for `docker build`:**\n\n```javascript\n{\n  prefix: '--build-arg',\n  patterns: ['**/*.arg']\n},\n{\n  prefix: '--label',\n  patterns: ['**/*.lbl']\n}\n```\n\nAll files matching the glob pattern `**/*.arg` and `**/*.lbl` would be read and a command generated from those arguments.\n\nWhen the command arguments are evaluated, a finalized command string is generated from those file contents.\n\n### Builder Options\n\n#### rootDir\n\nRoot directory to resolve all paths from.\n\n##### Default\n\n`process.cwd()`\n\n#### dynamicVariables\n\nKey-Value map containing the name of the variable and its value.\n\n##### Possible values\n\n ```typescript\n[key: string]: string | (() =\u003e string);\n```\n\n##### Example\n\n```typescript\n{\n  BUILD_DATE: () =\u003e new Date().toISOString().slice(0, 10),\n  VERSION: '1.0.0'\n}\n```\n\n#### skip/warn/throw UnresolvedVariables\n\nHandling of unresolved variables. These are the possible options:\n\n- `skipUnresolvedVariables` (Default: `false`)\n  - Skip command arguments where variables have no value\n- `warnUnresolvedVariables` (Default: `true`)\n  - Warn on command arguments where variables have no value\n- `throwUnresolvedVariables` (Default: `false`)\n  - Throw exception on command arguments where variables have no value\n\n#### variablePattern\n\nRegExp pattern for matching variables.\n\nFor example: `${SOME_VARIABLE}`\n\n##### Default\n\n`/\\$\\{(.+)\\}/`\n\n#### lineIgnorePattern\n\nRegExp pattern for ignoring lines in files when generating arguments.\n\nFor example: `# Some comment` or `// Some comment`\n\n##### Default\n\n`/^(\\#|\\/{2,})/`\n\n#### convertVariables\n\nConvert variables based on format. An example would be to convert Windows environment variables to Linux or vice versa.\n\nFor example: `%FOO% -\u003e $FOO`\n\n##### Possible values\n\n ```typescript\nfalse\n  | [\n      true,\n      {\n        from: RegExp;\n        to: string;\n      }\n    ];\n```\n\n##### Example\n\n```typescript\n[true, { from: /\\%([A-Z]+)\\%/, to: '$$$1' }]\n```\n\nThis would convert all Windows variables `%FOO%` to Linux variables `$FOO`\n\n#### shell\n\nShell to use for executing commands\n\n##### Default\n\n`/bin/bash`\n\n#### transformers\n\nTransformer is an object which consists of two parts: `predicate` and `replacer`.\n\n- `predicate` is a function that returns a boolean.\n- `replacer` is a function that returns a new value.\n\n\n##### Example\n\nHere's a simple *transformer* that surrounds sentences in quotes.\n\n```typescript\nsentencesInQuotes: {\n  predicate: (val: string): boolean =\u003e {\n    if (!val) return false;\n    return val.split(' ').length \u003e 1;\n  },\n  replacer: (val: string): string =\u003e `\"${val}\"`\n}\n```\n\n## API\n\n### IBuilder\n\n```typescript\noptions: IBuilderOptions;\n/**\n * Create a new command and register it in the builder\n * @param command Main command, e.g. 'docker build'\n * @param filePatterns Command argument prefix and glob file patterns\n * @returns A new command object\n */\ncreateCommand(\n  command: string,\n  filePatterns?: IArgumentFilePatterns[]\n): ICommand;\n\n/**\n * Get all commands that are registered in the builder\n * @returns Array of command objects\n */\ngetAllCommands(): ICommand[];\n```\n\n### ICommand\n\n```typescript\n/**\n * Executes a command\n * @param stdout Callback on STDOUT\n * @param stderr Callback on STDERR\n */\nexec(\n  stdout?: (chunk: string) =\u003e void,\n  stderr?: (chunk: string) =\u003e void\n): ICommandProcess;\n\n/**\n * Prepend an argument\n * @param argument Argument\n */\nprependArgument(argument: TCommandArgumentInput): ICommand;\n\n/**\n * Append an argument\n * @param argument Argument\n */\nappendArgument(argument: TCommandArgumentInput): ICommand;\n\n/**\n * Get the command string\n */\ntoString(): string;\n\n/**\n * Get the command string as an array\n */\ntoArray(): ReadonlyArray\u003cstring\u003e;\n```\n\n## Roadmap\n\n- Set up automated TypeScript documentation for APIs\n- Follow [Conventional Commits](https://www.conventionalcommits.org)\n- Set up CI to run automated tests\n- Plugin / Middleware architecture\n  - Ability to hook into events\n  - Ability to add custom behavior with middlewares\n  - Ability to create custom transformers\n- CLI\n- Optimizations + asynchronous operations\n- Batch command handling\n- Interactive process attaching, e.g. for `docker run -it`\n\n## Contributing\n\nAll contributions are very well appreciated. Just fork this repo and [submit a PR](https://help.github.com/articles/about-pull-requests/)!\n\nJust remember to run the following beforehand:\n\n- `npm test`\n- `npm run typecheck`\n- `npm run format`\n- `npm run lint`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaui%2Fargster","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgaui%2Fargster","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaui%2Fargster/lists"}