{"id":13394272,"url":"https://github.com/jondot/hygen","last_synced_at":"2025-05-12T15:29:40.708Z","repository":{"id":38375446,"uuid":"100161483","full_name":"jondot/hygen","owner":"jondot","description":"The simple, fast, and scalable code generator that lives in your project.","archived":false,"fork":false,"pushed_at":"2024-07-09T11:40:47.000Z","size":10500,"stargazers_count":5779,"open_issues_count":105,"forks_count":265,"subscribers_count":52,"default_branch":"master","last_synced_at":"2025-05-10T11:35:06.660Z","etag":null,"topics":["cli","generator","nodejs","tools"],"latest_commit_sha":null,"homepage":"http://www.hygen.io","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/jondot.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":"2017-08-13T07:38:43.000Z","updated_at":"2025-05-09T06:30:41.000Z","dependencies_parsed_at":"2024-01-06T01:57:22.238Z","dependency_job_id":"a6bce8ea-197f-44c4-abef-1403d291dba4","html_url":"https://github.com/jondot/hygen","commit_stats":{"total_commits":454,"total_committers":58,"mean_commits":7.827586206896552,"dds":0.2422907488986784,"last_synced_commit":"26f76d8dede565b2bf38d0b9e9f3009ee2c8f9ae"},"previous_names":[],"tags_count":83,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jondot%2Fhygen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jondot%2Fhygen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jondot%2Fhygen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jondot%2Fhygen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jondot","download_url":"https://codeload.github.com/jondot/hygen/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253584492,"owners_count":21931547,"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","generator","nodejs","tools"],"created_at":"2024-07-30T17:01:14.494Z","updated_at":"2025-05-12T15:29:40.682Z","avatar_url":"https://github.com/jondot.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","Repositories","*.js","cli","📦 Legacy \u0026 Inactive Projects","Node"],"sub_categories":["File","Node","工具库"],"readme":"\u003ch3 align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/jondot/hygen/master/media/hygen.png\" alt=\"hygen logo\" width=400 /\u003e\n\u003c/h3\u003e\n\n[![build status](https://img.shields.io/travis/jondot/hygen/master.svg)](https://travis-ci.org/jondot/hygen)\n[![npm version](https://img.shields.io/npm/v/hygen.svg)](https://www.npmjs.com/package/hygen)\n\n`hygen` is the simple, fast, and scalable code generator that lives _in_ your project.\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/jondot/hygen/master/media/hygen.gif\" width=600/\u003e\n\u003c/div\u003e\n\n\n## Features\n\n- ✅ Build ad-hoc generators quickly and full on project scaffolds.\n- ✅ Local generators per project (and global, if you must)\n- ✅ Built-in scaffolds to quickly create generators\n- ✅ Full logic templates and rendering\n- ✅ Prompts and flows for taking in arguments\n- ✅ Automatic CLI arguments\n- ✅ Adding new files\n- ✅ Injecting into existing files\n- ✅ Running shell commands\n- ✅ Super fast, constantly optimized for speed\n\n\n\u003e New in hygen v4.0.0: a positional `NAME` parameter.\n\u003e Now you can use `$ hygen component new MyComponent` instead of `$ hygen component new --name MyComponent`.\n\n## Used By\n\n\u003cImage alt=\"Wix\" height=\"32\" src=\"https://upload.wikimedia.org/wikipedia/en/7/76/Wix.com_website_logo.svg\"/\u003e \u0026nbsp; \u0026nbsp; \u003cImage alt=\"Airbnb\" height=\"50\" src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/6/69/Airbnb_Logo_B%C3%A9lo.svg/512px-Airbnb_Logo_B%C3%A9lo.svg.png\"/\u003e \u0026nbsp; \u0026nbsp; \u003cImage alt=\"Mercedes Benz AG\" height=\"60\" src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/Mercedes-Benz_Logo_2010.svg/320px-Mercedes-Benz_Logo_2010.svg.png\"/\u003e \u0026nbsp; \u0026nbsp; \u003cImage alt=\"Open Data Institute\" height=\"60\" src=\"https://luminategroup.com/storage/538/c/opendatainstitute%28ODI%29-logo%402x-logo.png\"/\u003e \u0026nbsp; \u0026nbsp;  \u003cImage alt=\"Ableneo\" height=\"80\" src=\"https://www.ableneo.com/web/images/logo.svg\"/\u003e \u0026nbsp;\n\u003cImage alt=\"City of Amsterdam\" height=\"70\" src=\"https://avatars3.githubusercontent.com/u/14022058?s=200\u0026v=4\"/\u003e \u0026nbsp; \u0026nbsp; \u003cImage alt=\"Accenture\" height=\"80\" src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/c/cd/Accenture.svg/512px-Accenture.svg.png\"/\u003e  \u0026nbsp; \u003cImage alt=\"Birdie\" height=\"60\" src=\"https://assets.website-files.com/5d07a11d8195605723dbff07/5d09430b3d6e1c5d28a6e2b6_global%E2%80%94birdie_logo_black.svg\"/\u003e \u0026nbsp; \u0026nbsp;\n\u003cImage alt=\"Kind\" height=\"80\" src=\"https://madebykind.com/dist/images/logos/site-logo-green-e0e983ec46.svg\"/\u003e \u0026nbsp; \u0026nbsp;  \u003cImage alt=\"Ackee\" height=\"80\" src=\"https://avatars3.githubusercontent.com/u/1728223?s=400\u0026v=4\"/\u003e \u0026nbsp;\n \u003cImage alt=\"Aerian Studios\" height=\"80\" src=\"https://www.aerian.com/img/c/aerian-logo.svg\"/\u003e \u0026nbsp;\u003cImage alt=\"Food and Agriculture Organization of the UN\" height=\"100\" src=\"https://avatars2.githubusercontent.com/u/38506195?s=200\u0026v=4\"/\u003e \u003cImage alt=\"Cape Cod Commision\" height=\"70\" src=\"http://www.capecodcommission.org/gfx/home-logo.jpg\"/\u003e \u0026nbsp; \u003cImage alt=\"Tweak Things\" height=\"80\" src=\"https://avatars3.githubusercontent.com/u/49718812?s=400\u0026v=4\"/\u003e \u0026nbsp; \u0026nbsp; \u003cImage alt=\"Crema\" height=\"40\" src=\"https://assets.website-files.com/5b6b50e79e9b6f5948395973/5d88f52b42420350d3e117d2_Asset%201.png\"/\u003e \u0026nbsp; \u0026nbsp; \u003cImage alt=\"Cureon\" height=\"120\" src=\"http://cureon.de/resources/cureon_logo.png\"/\u003e \u0026nbsp; \u0026nbsp; \u003cImage alt=\"Astrocoders\" height=\"50\" src=\"https://d33wubrfki0l68.cloudfront.net/b8f71088a0c9bc92d67476a361f35690d157d0e5/517c2/static/logo-c5d890fb431b53a7c61800feccd65ac2.png\"/\u003e \u0026nbsp; \u0026nbsp; \u003cImage alt=\"Vega/IDL\" height=\"60\" src=\"http://vega.github.io/images/idl-logo.png\"/\u003e \u0026nbsp; \u003cImage alt=\"Sporty Spots\" height=\"60\" src=\"https://www.sportyspots.com/static/sportyspots.svg\"/\u003e \u0026nbsp; \u0026nbsp;\u003cImage alt=\"Thrashplay\" height=\"50\" src=\"https://avatars1.githubusercontent.com/u/55868193?s=200\u0026v=4\"/\u003e \u0026nbsp;\u0026nbsp;\u003cImage alt=\"8base\" height=\"80\" src=\"https://avatars1.githubusercontent.com/u/28789399?s=200\u0026v=4\"/\u003e \u0026nbsp;\u0026nbsp; \u003cImage alt=\"Instamotionh\" height=\"50\" src=\"https://avatars1.githubusercontent.com/u/44466967?s=200\u0026v=4\"/\u003e  \u003cImage alt=\"Biotope\" height=\"90\" src=\"https://avatars1.githubusercontent.com/u/34653144?s=400\u0026v=4\"/\u003e \u003cImage alt=\"Frontend Labs\" height=\"50\" src=\"https://avatars1.githubusercontent.com/u/6691550?s=200\u0026v=4\"/\u003e\n\u003cImage alt=\"Swydo\" height=\"90\" src=\"https://avatars1.githubusercontent.com/u/1563883?s=400\u0026v=4\"/\u003e \u003cImage alt=\"Gridsome\" height=\"70\" src=\"https://avatars0.githubusercontent.com/u/17981963?s=200\u0026v=4\"/\u003e \u003cImage alt=\"Rosem Laboratory\" height=\"90\" src=\"https://avatars2.githubusercontent.com/u/22129460?s=200\u0026v=4\"/\u003e\u003cImage alt=\"Sheffield Hallam University\" height=\"70\" src=\"https://avatars1.githubusercontent.com/u/46559136?s=400\u0026v=4\"/\u003e\n\u003cImage alt=\"Hackoregon\" height=\"80\" src=\"https://avatars3.githubusercontent.com/u/6343574?s=400\u0026v=4\"/\u003e \u003cImage alt=\"Chilly Design\" height=\"50\" src=\"https://avatars1.githubusercontent.com/u/13002395?s=200\u0026v=4\"/\u003e\n\n\u003cImage alt=\"Scale Leap\" height=\"50\" src=\"https://avatars3.githubusercontent.com/u/41709180?s=200\u0026v=4\"/\u003e\n\n\u003cImage alt=\"Chat Logs\" height=\"50\" src=\"https://avatars1.githubusercontent.com/u/37252774?s=200\u0026v=4\"/\u003e\n\n\u003cImage alt=\"Stelace\" height=\"70\" src=\"https://avatars1.githubusercontent.com/u/32740360?s=400\u0026v=4\"/\u003e\n\n\u003cImage alt=\"Echobind.\" height=\"70\" src=\"https://avatars0.githubusercontent.com/u/570840?s=200\u0026v=4\"/\u003e\n\n## Quick Start\n\nHygen can be used to supercharge your workflow with [Redux](https://hygen.io/docs/redux), [React Native](https://hygen.io/docs/react-native), [Express](https://hygen.io/docs/express) and more, by allowing you avoid manual work and generate, add, inject and perform custom operations on your codebase.\n\nIf you're on macOS and have Homebrew:\n\n```\n$ brew tap jondot/tap\n$ brew install hygen\n```\n\nIf you have node.js installed, you can install globally with `npm` (or Yarn):\n\n```\n$ npm i -g hygen\n```\n\nIf you like a no-strings-attached approach, you can use `npx` without installing globally:\n\n```\n$ npx hygen ...\n```\n\nFor other platforms, see [releases](https://github.com/jondot/hygen/releases).\n\nInitialize `hygen` in your project (do this once per project):\n\n```\n$ cd your-project\n$ hygen init self\n```\n\nBuild your first generator, called `mygen`:\n\n```\n$ hygen generator new mygen\n\nLoaded templates: _templates\n       added: _templates/mygen/new/hello.ejs.t\n```\n\nNow you can use it:\n\n```\n$ hygen mygen new\n\nLoaded templates: _templates\n       added: app/hello.js\n```\n\nYou've generated content into the current working directory in `app/`. To see how the generator is built, look at `_templates` (which you should check-in to your project from now on, by the way).\n\nYou can build a generator that uses an interactive prompt to fill in a variable:\n\n```\n$ hygen generator with-prompt mygen\n\nLoaded templates: _templates\n       added: _templates/mygen/with-prompt/hello.ejs.t\n       added: _templates/mygen/with-prompt/prompt.js\n```\n\nDone! Now let's use `mygen`:\n\n```\n$ hygen mygen with-prompt\n? What's your message? hello\n\nLoaded templates: _templates\n       added: app/hello.js\n```\n\n## Use a template repo\n\nWant to start from a repo?\n\n```\n$ hygen init repo antfu/vitesse --to my-folder\n```\n\nWant to start from an existing repo on an existing project?\n\n```\n$ mkdir your-project \u0026\u0026 cd your-project\n$ hygen init repo antfu/vitesse\n```\n\n\n## What's Next?\n\nGo to the [documentation](https://hygen.io/docs/quick-start) to get to know the rest of Hygen and generators.\n\nIf you're in a hurry:\n\n* To learn how to edit generator templates, [look here](https://hygen.io/docs/templates)\n* To see how to use generators [look here](https://hygen.io/docs/generators)\n* Take a look at the [ecosystem](https://hygen.io/docs/packages) and tooling built around Hygen.\n\n## A Different Kind of a Generator\n\n`hygen` is a scalable generator. It has developer and team ergonomics as first priority.\n\nIt avoids \"blessed\" or dedicated projects that codifies code generation, which before you know it, become a product you build, needs testing, CI, separate pull request reviews, and ultimately sucks up your time and becomes this super hated thing no one likes to touch anymore.\n\nPlus, since they are not the product you are building they become notoriously hard to reason about.\n\n## Scratch Your Own Itch\n\nBecause `hygen` templates live _in_ your project, it cuts the time from having an itch for generating code (Redux, anyone?) in your current\nproject to code generated with it and others benefiting from it.\n\n### Template Locality\n\n`hygen` picks up a local `_templates` folder\nat any folder level of your project you're working from.\n\nThis is important because:\n\n* Templates are project-local. A git clone of the project fetches all generators as well.\n* Different generators can be tucked in different parts of the project, making it contextual.\n* Template locality is scalable; different teams can maintain different generators.\n* When you change your code, you can make changes in the template and pack in the same commit, to be reviewed and merged in the same PR (as opposed to installing different \"plugins\" or different templates from out-of-repo places).\n\nAnd yet, if you don't like project-local templates:\n\n* You can have a global `_templates` folder (maybe a central git repo you maintain?) by populating an environment variable `HYGEN_TMPLS`\n* You can build a [custom generator](#build-your-own) of your own with `hygen` at its core, and pack your own templates with it.\n\n### Folder Structure is Command Structure\n\nThe templates folder structure _maps directly_ to the command structure:\n\n```\n$ hygen worker new jobrunner\n```\n\nFor this command, `hygen worker new` maps to `_templates/worker/new` and all files within `worker/new` are rendered.\n\nTemplate parameters are given with `--flag VALUE`, as many as you'd like. In this example we've set a parameter named `name` to the value `jobrunner`.\n\n### Subcommands\n\nA subcommand is a file inside a your folder structure. So if the structure is this:\n\n```\n_templates/\n    worker/\n      new/\n        index.html.ejs\n        setup.html.ejs\n```\n\nAnd you only want `setup`, you can run:\n\n```\n$ hygen worker new:setup\n```\n\nYou can also use the subcommand as a regular expression so, these will do the same:\n\n```\n$ hygen worker new:se\n```\n\n```\n$ hygen worker new:se.*\n```\n\n### Frontmatter for Decluttering\n\nHere's how a template looks like (in our example, `index.ejs.t`). Templates bodies are [ejs](https://github.com/tj/ejs):\n\n```javascript\n---\nto: app/workers/\u003c%=name%\u003e.js\n---\n\nclass \u003c%= h.capitalize(name) %\u003e {\n    work(){\n        // your code here!\n    }\n}\n```\n\nThe first part of the template is a [front matter](https://jekyllrb.com/docs/frontmatter/), idea borrowed from Markdown, this is the metadata part of a `hygen` template and is part of the reason of why your templates will feel more lightweight and flexible.\n\nAll frontmatter metadata _are also run through the template engine_ so feel free to use variables in the frontmatter as you wish.\n\nThere's one required metadata variable: `to`.\n`to` points to where this file will be placed (folders are created as needed).\n\n### Case changing\n\n`hygen` provides ability to semantic case changing with `change-case` library, it's simple to use and very easy to understand.\n\nThere is a usecase for react based components generation:\n\n```yaml\n---\nto: components/\u003c%= name %\u003e/index.jsx\n---\nimport React from 'react'\n\nexport const \u003c%= name %\u003e = ({ children }) =\u003e (\n  \u003cdiv className=\"\u003c%= h.changeCase.paramCase(name) %\u003e\"\u003e{children}\u003c/div\u003e\"\n)\n```\n\nWith name `HelloWorld` will be compiled to:\n\n```js\nimport React from 'react'\n\nexport const HelloWorld = ({ children }) =\u003e (\n  \u003cdiv className=\"hello-world\"\u003e{children}\u003c/div\u003e\"\n)\n```\n\nYou can see the full list [here](https://github.com/blakeembrey/change-case).\n\n### Addition, Injection, and More\n\nBy default templates are 'added' to your project as a new target file, but you can also choose to inject a template _into_ an existing target file.\n\nFor this to work, you need to use `inject: true` with the accompanied inject-specific props.\n\n```yaml\n---\nto: package.json\ninject: true\nafter: dependencies\nskip_if: react-native-fs\n---\n\"react-native-fs\":\"*\",\n```\n\nThis template will add the `react-native-fs` dependency into a `package.json` file, but it will not add it twice (see `skip_if`).\n\nHere are the available mutually-exclusive options for where to inject at:\n\n* `before | after` - a regular expression / text to locate. The inject line will appear before or after the located line.\n* `prepend | append` - add a line to start or end of file respectively.\n* `line_at` - add a line at this exact line number.\n\nYou can guard against double injection:\n\n* `skip_if` - a regular expression / text. If exists injection is skipped.\n\nAlso you can insert or remove empty line to injection body. That feature very useful if your editor or formatter automatically insert blank line at the end of file on save:\n\n* `eof_last` - if falsy - trim blank line from the end of injection body, if truthy - insert it.\n\n### Build Your Own\n\n`hygen` is highly embeddable. You should be able to use it by simply listing it\nas a dependency and having [this kind of workflow](src/bin.ts) in your binary.\n\n```javascript\nconst { runner } = require('hygen')\nconst Logger = require('hygen/dist/logger')\nconst path = require('path')\nconst defaultTemplates = path.join(__dirname, 'templates')\n\nrunner(process.argv.slice(2), {\n  templates: defaultTemplates,\n  cwd: process.cwd(),\n  logger: new Logger.default(console.log.bind(console)),\n  createPrompter: () =\u003e require('enquirer'),\n  exec: (action, body) =\u003e {\n    const opts = body \u0026\u0026 body.length \u003e 0 ? { input: body } : {}\n    return require('execa').shell(action, opts)\n  },\n  debug: !!process.env.DEBUG\n})\n```\n\n# Development\n\nThe Hygen codebase has a functional style where possible. This is because naturally, it\nfeeds parameters and spits out files. Try to keep it that way.\n\nRunning `hygen` locally, rigged to your current codebase (note the additional `--` to allow passing flags)\n\n```\n$ yarn hygen -- mailer new foobar\n```\n\nRunning tests in watch mode:\n\n```\n$ yarn watch\n```\n\n## Metaverse Testing\n\nThe easiest way to make an impact is to use the built-in [`metaverse`](src/__tests__/metaverse) tests suite, and then add the tests [here](src/__tests__/metaverse.spec.js).\n\nThe idea here is to copy templates from any project that use `hygen` and to test that it works at all times. This keeps tabs on the hygen universe / ecosystem (nicknamed metaverse) and makes sure this test suite breaks before `hygen` clients break.\n\n## Internal Testing\n\n## Start Up Speed Testing\n\nMany generators become painfully slow to use as the thing you want to generate grow (because, real life),\n\nThis is why `hygen` takes speed as a first class citizen, and sports a dedicated start-up timing suite:\n\n```\n$ yarn test:require\n```\n\nIn addition, thought is given to which dependencies to take in, how their file structure fan out and what kind of disk access (due to `require`) would `hygen` ultimately have when we run it. This is recorded with every test run.\n\nBundling a single file was evaluated (and the infrastructure is still there, using `webpack`) and wasn't faster than what we have right now.\n\n# Contributing\n\nFork, implement, add tests, pull request, get my everlasting thanks and a respectable place here :).\n\n### Thanks:\n\nTo all [Contributors](https://github.com/jondot/hygen/graphs/contributors) - you make this happen, thanks!\n\n# Copyright\n\nCopyright (c) 2018 [Dotan Nahum](http://gplus.to/dotan) [@jondot](http://twitter.com/jondot). See [LICENSE](LICENSE.txt) for further details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjondot%2Fhygen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjondot%2Fhygen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjondot%2Fhygen/lists"}