{"id":21915530,"url":"https://github.com/terotests/robowr","last_synced_at":"2026-05-19T09:09:28.902Z","repository":{"id":32830639,"uuid":"143612175","full_name":"terotests/robowr","owner":"terotests","description":"Code Generator","archived":false,"fork":false,"pushed_at":"2023-01-06T02:11:33.000Z","size":866,"stargazers_count":0,"open_issues_count":15,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-03T01:41:32.824Z","etag":null,"topics":["codegeneration","codewriter","generators","writer"],"latest_commit_sha":null,"homepage":"","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/terotests.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":"2018-08-05T12:46:38.000Z","updated_at":"2022-04-21T22:04:26.000Z","dependencies_parsed_at":"2023-01-14T22:22:09.247Z","dependency_job_id":null,"html_url":"https://github.com/terotests/robowr","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/terotests/robowr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terotests%2Frobowr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terotests%2Frobowr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terotests%2Frobowr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terotests%2Frobowr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/terotests","download_url":"https://codeload.github.com/terotests/robowr/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terotests%2Frobowr/sbom","scorecard":{"id":874564,"data":{"date":"2025-08-11","repo":{"name":"github.com/terotests/robowr","commit":"c0fcdd7a123731ff40cb70bd9f5e2e6fa44619e2"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.3,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","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":"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":"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":"Code-Review","score":0,"reason":"Found 0/17 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":"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":"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":"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":"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":"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":"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":"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":"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":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 17 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":0,"reason":"34 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-3f95-r44v-8mrg","Warn: Project is vulnerable to: GHSA-28xr-mwxg-3qc8","Warn: Project is vulnerable to: GHSA-9p95-fxvg-qgq2","Warn: Project is vulnerable to: GHSA-9w5j-4mwv-2wj8","Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-w573-4hg7-7wgq","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-4q6p-r6v2-jvc5","Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-5fw9-fq32-wv5p","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-g6ww-v8xp-vmwg","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-jgrx-mgxx-jf9v","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-j8xg-fqg3-53r7","Warn: Project is vulnerable to: GHSA-6fc8-4gx4-v693","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q","Warn: Project is vulnerable to: GHSA-c4w7-xm78-47vh"],"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-24T05:28:51.591Z","repository_id":32830639,"created_at":"2025-08-24T05:28:51.591Z","updated_at":"2025-08-24T05:28:51.591Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33209603,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-19T07:54:09.561Z","status":"ssl_error","status_checked_at":"2026-05-19T07:54:08.508Z","response_time":58,"last_error":"SSL_read: 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":["codegeneration","codewriter","generators","writer"],"created_at":"2024-11-28T19:12:39.579Z","updated_at":"2026-05-19T09:09:28.884Z","avatar_url":"https://github.com/terotests.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Robowr Code Generator Library 3.0\n\nRobowr is a code generator, which can generate any code that can be written in text format.\n\n# New: Code difference added to code writer\n\nCurrent version adds `useDiff` option, which is enabled by default. Each directory will have `.diff` subdirectory which\nis generated for the purpose of diffing the originally written file to the current version.\n\n1. If the files are not changed, the code generator will overrride changes\n2. If the files are changed the code generator will follow the changes made in the changed files\n\n```\n    R.CreateContext({})\n      .file(\"./\", \"diff_test.ts\")\n      .write([`if(true) {`, [[`console.log(\"OK\");`]], `}`])\n      .save(\"./test/difftest\", { useDiff: true, usePrettier: true });\n```\n\n# Installing\n\n```\nnpm i -g robowr\n```\n\n# Create a simple generator from command line\n\nYou can start creating generators from scratch but sometimes it is easier to create them from source code automatically.\n\nBasicly what you need is just a source file to transform to a generator. The generated generator will include the source code\nfor re-creating the given file. You can then use the generated generator to generate more similar files.\n\n## From stdin\n\n```\ncat hello.ts | robowr\n```\n\n```\ncat hello.ts | robowr -o gen/HelloWorld.ts\n```\n\n## Import File as generator template\n\n```\nrobowr -f docker-compose.yml\n```\n\nor if you want to specify the output file\n\n```\nrobowr -f docker-compose.yml -o createDocker.ts\n```\n\nTo create it you can use for example `ts-node`\n\n```\nts-node createDocker.ts\n```\n\n# Using programmatically\n\nExample of creating some static HTML content. Notice that using the context variables is absolutely optional.\nIn the example they are used to define `title` and imported scripts for the HTML files. It is absolutely\nfine to use anything else to manage internal state of the generator.\n\n```typescript\nimport * as R from \"robowr\";\n\nconst head = (code: any) =\u003e [\"\u003chead\u003e\", [[code]], \"\u003c/head\u003e\"];\nconst title = (code: any) =\u003e [\"\u003ctitle\u003e\", [[code]], \"\u003c/title\u003e\"];\nconst script = (code: string) =\u003e [`\u003csrcipt src=\"${code}\"\u003e\u003c/script\u003e`];\nR.CreateContext({\n  title: \"Sample\",\n  scriptFiles: [\"src/utils.js\", \"src/index.js\"],\n})\n  .file(\"./\", \"index.html\")\n  .write([\n    \"\u003chtml\u003e\",\n    (ctx) =\u003e\n      head([\n        title(ctx.data.title + \" Index\"),\n        ctx.data.scriptFiles.map(script),\n      ]),\n    [\n      [\n        // \u003c-- indentation\n        \"\u003cbody\u003e\",\n        [[\"Genrated Index\"]],\n        \"\u003c/body\u003e\",\n      ],\n    ],\n    \"\u003c/html\u003e\",\n  ])\n  .file(\"./\", \"home.html\")\n  .write([\n    \"\u003chtml\u003e\",\n    (ctx) =\u003e head(title(ctx.data.title + \" Home\")),\n    [\n      [\n        // \u003c-- indentation\n        \"\u003cbody\u003e\",\n        [[\"Generated Home\"]],\n        \"\u003c/body\u003e\",\n      ],\n    ],\n    \"\u003c/html\u003e\",\n  ])\n  .save(\"./static/\");\n```\n\n# Examples\n\nContexts are generic, so you can use any support data as parameter to the writer.\n\nFirst initialize the context\n\n```typescript\nimport * as R from \"robowr\";\n\n// The data used by the robowr\nconst data = {\n  values: [\"value1\", \"value2\", \"value3\"],\n};\nconst ctx = R.CreateContext({ values: [] });\n```\n\nThen you can create code using the context and return string, arrays, nested arrays (blocks)\nor functions which will be evaluated lazily.\n\n```typescript\nconst newCtx = R.Walk(ctx, (ctx) =\u003e [\n  `switch( value ) {`,\n  ...ctx.data.values.map((name) =\u003e [\n    [`case \"${name}\":`, [[`console.log(\"Found value ${name}\");`, \"break;\"]]],\n  ]),\n  \"}\",\n]);\n```\n\nTo get the code call `newCtx.writer.getCode()`\n\n```typescript\n// The generated code from above\nswitch (value) {\n  case \"value1\":\n    console.log(\"Found value value1\");\n    break;\n  case \"value2\":\n    console.log(\"Found value value2\");\n    break;\n  case \"value3\":\n    console.log(\"Found value value3\");\n    break;\n}\n```\n\nSince context is passed to callback functions you can use them to fine grained control of the\ngenerator or you can use then just to make code easier to write\n\n```typescript\n// simple function returning a comment block\nconst CreateIfNode = \u003cT extends R.hasWriter\u003e(\n  condition: R.CodeBlock\u003cT\u003e,\n  thenBlock: R.CodeBlock\u003cT\u003e,\n  elseBlock?: R.CodeBlock\u003cT\u003e\n) =\u003e {\n  return [\n    R.Join([\"if(\", condition, \") {\"]),\n    [[thenBlock]],\n    elseBlock ? [\"} else {\", [[elseBlock]], \"}\"] : \"}\",\n  ];\n};\n```\n\n```typescript\nR.Walk(ctx, [\n  CreateIfNode(\n    \"x \u003e 10\",\n    \"console.log('x was bigger than ten');\",\n    \"console.log('x was smaller or equal to ten');\"\n  ),\n]);\n```\n\n## Modifying context by the generators\n\nSometimes you want to modify the context before the output is written, for example you can\nrun multipled passes to the context before actually outputting any code.\n\nThis is very simple, any callback function can simply modify the data variable in the context\n\n```typescript\nconst ctx = R.CreateContext({ users: [] });\nconst newCtx = R.Walk(ctx, (ctx) =\u003e {\n  ctx.data.users.push(\"New User\");\n});\n```\n\n### Immutable context\n\nContext can be immutable, you can use any immutable library with the context data or you can\nuse the built-in Immer -support like this\n\n```typescript\nexpect(\n  R.Walk(R.CreateContext({ cnt: 1 }), [\n    (ctx) =\u003e\n      ctx.produce((d) =\u003e {\n        d.cnt++;\n      }),\n    (ctx) =\u003e\n      ctx.produce((d) =\u003e {\n        d.cnt++;\n      }),\n  ]).data.cnt\n).to.equal(3);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fterotests%2Frobowr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fterotests%2Frobowr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fterotests%2Frobowr/lists"}