{"id":19502156,"url":"https://github.com/cyberagent/moldable","last_synced_at":"2025-06-28T11:36:12.896Z","repository":{"id":239808730,"uuid":"781851990","full_name":"CyberAgent/moldable","owner":"CyberAgent","description":"A CLI NPM Package for code generation","archived":false,"fork":false,"pushed_at":"2025-04-16T21:52:13.000Z","size":437,"stargazers_count":23,"open_issues_count":3,"forks_count":0,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-05-22T11:57:49.608Z","etag":null,"topics":["cli","code-generator","golang","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/moldable","language":"Go","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/CyberAgent.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-04-04T06:54:58.000Z","updated_at":"2024-12-22T05:58:42.000Z","dependencies_parsed_at":"2024-05-15T15:07:59.785Z","dependency_job_id":null,"html_url":"https://github.com/CyberAgent/moldable","commit_stats":null,"previous_names":["cyberagent/moldable"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/CyberAgent/moldable","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CyberAgent%2Fmoldable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CyberAgent%2Fmoldable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CyberAgent%2Fmoldable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CyberAgent%2Fmoldable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CyberAgent","download_url":"https://codeload.github.com/CyberAgent/moldable/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CyberAgent%2Fmoldable/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261475841,"owners_count":23164055,"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","code-generator","golang","typescript"],"created_at":"2024-11-10T22:15:26.142Z","updated_at":"2025-06-28T11:36:12.874Z","avatar_url":"https://github.com/CyberAgent.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![CI](https://github.com/CyberAgent/moldable/actions/workflows/ci.yaml/badge.svg)](https://github.com/CyberAgent/moldable/actions/workflows/ci.yaml)\n\n# `moldable`\n\nA CLI tool for code generation under the influence of [plop](https://plopjs.com) and [scaffdog](https://scaff.dog). It has the best of each tool, yet it is faster and more flexible.\nSee the [benchmarks](#benchmarks) for more information.\n\n## Installation\n\n```bash\nnpm install -g moldable\n```\n\n## Quick Start\n\nCreate a `.moldable` folder in the root directory of your application, and create Markdown file within it shown below. Name the file `quick-start.md`.\n\n````md\n---\nname: \"quick-start\"\ndescription: \"Quick Start\"\nprompts:\n  - type: \"base\"\n    name: \"name\"\n    message: \"Type your name\"\n    validate: \"{{if eq (len .input) 0}}Name must have more than - characters{{end}}\"\n  - type: \"select\"\n    name: \"favoriteColor\"\n    message: \"Select your favorite color\"\n    choices:\n      - \"Red\"\n      - \"Green\"\n      - \"Blue\"\nactions:\n  - type: \"add\"\n    path: \"src/quick-start.json\"\n    template: \"quick-start.json\"\n---\n\n# quick-start.json\n\n```json\n{\n  \"name\": \"{{.name}}\",\n  \"favoriteColor\": \"{{.favoriteColor}}\"\n}\n```\n````\n\nExecute `moldable` in the root directory of your application, and select the `quick-start` generator.\n\n```bash\n# Answer the questions\n? Select Generator:\n  ▸ quick-start - Quick Start\n\n✔  Type your name : John Doe█\n\n?  Select your favorite color :\n  ▸ Red\n    Green\n    Blue\n\n# Results\n🖨  Added:\n  src/quick-start.json\n```\n\nAnswer the questions that appear, and the code will be generated in the `quick-start.json` file.\n\n```json\n{\n  \"name\": \"John Doe\",\n  \"favoriteColor\": \"Red\"\n}\n```\n\n## Advanced Usage\n\nYou can describe a generator for generating any code.\nCreate a `/.moldable` folder in the root directory of your application,\nand create Markdown files within it.\n\n```\n.\n└──  .moldable\n    ├── foo.md\n    └── bar.md\n```\n\nThe name of the Markdown file corresponds to the generator name displayed when you launch moldable.\nWhen you run moldable, an interactive question starts according to the selected generator, and when all are answered, code is generated.\nThis generator is divided into metadata (in YAML format) and content (in Markdown format).\nThe structure of the metadata is as follows. You can use the syntax of Go's [text/template](https://pkg.go.dev/text/template) in some properties.\n\n| Name        | Description                                                                   | Required           | Type             | Example                                                                                                      |\n| ----------- | ----------------------------------------------------------------------------- | ------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------ |\n| name        | Template name (must match the Markdown file name)                             | :white_check_mark: | String           | \"pages\"                                                                                                      |\n| description | Template description                                                          | :white_check_mark: | String           | \"Page Generator\"                                                                                             |\n| prompts     | Questions to be asked sequentially after selecting a template                 | :white_check_mark: | Array of mapping | \u003cpre\u003etype: \"base\"\u003cbr\u003ename: \"name\"\u003cbr\u003emessage: \"Type a page name\"\u003cbr\u003e\u003c/pre\u003e                                   |\n| actions     | Settings for generating code using the values of the answers to the questions | :white_check_mark: | Array of mapping | \u003cpre\u003etype: \"add\"\u003cbr\u003epath: \"src/app/{{.name}}/page.tsx\"\u003cbr\u003etemplate: \"{{.name \\| pascal}}/page.tsx\"\u003cbr\u003e\u003c/pre\u003e |\n\nThe structure of each element of the prompts value is as follows.\n\n| Name          | Description                                                                                                                                            | Required                                  | Type                                             |\n| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------- | ------------------------------------------------ |\n| type          | Format of the question\u003cbr\u003e・base: Text input\u003cbr\u003e・select: Single selection\u003cbr\u003e・multiselect: Multiple selection\u003cbr\u003e・confirm: Y/N binary choice        | :white_check_mark:                        | \"base\" \\| \"select\" \\| \"multiselect\" \\| \"confirm\" |\n| name          | Variable name to store the result of the question. In places where text/template is valid, it can be referenced with a . start.                        | :white_check_mark:                        | String                                           |\n| message       | Content of the question                                                                                                                                | :white_check_mark:                        | String                                           |\n| prefix        | Supplement to the question, displayed before the question                                                                                              |                                           | String                                           |\n| suffix        | Supplement to the question, displayed after the question                                                                                               |                                           | String                                           |\n| when          | Place to skip the question. The results of the questions up to the current question can be referenced.                                                 |                                           | String(text/template)                            |\n| validate      | Place to validate the question. The value of the question being entered can be referenced with .input.                                                 |                                           | String(text/template)                            |\n| defaultValues | Default value of the result of the question\u003cbr\u003eData type\u003cbr\u003e・base: String\u003cbr\u003e・select: String\u003cbr\u003e・multiselect: Array of String\u003cbr\u003e・confirm: Boolean |                                           | Any                                              |\n| choises       | Choices for select and multiselect                                                                                                                     | Required if type is select or multiselect | Array of String                                  |\n\nThe structure of each element of the actions value is as follows.\n\n| Name     | Description                                                               | Required                   | Type                  |\n| -------- | ------------------------------------------------------------------------- | -------------------------- | --------------------- |\n| type     | Type of code generation                                                   | :white_check_mark:         | \"add\" \\| \"append\"     |\n| path     | Destination of the code output                                            | :white_check_mark:         | String(text/template) |\n| template | Template name for code generation (must match the heading in the content) | :white_check_mark:         | String(text/template) |\n| skip     | Place to skip code generation                                             |                            | String(text/template) |\n| pattern  | Destination to add code in append                                         | Required if type is append | String                |\n\nIn addition, for variables referenced within text/template, you can convert to the following cases using the format .var | case.\n\n| Name     | Case          |\n| -------- | ------------- |\n| camel    | camelCase     |\n| snake    | snake_case    |\n| kebab    | kebab-case    |\n| dash     | dash-case     |\n| dot      | dot.case      |\n| proper   | ProperCase    |\n| pascal   | PascalCase    |\n| lower    | lower case    |\n| sentence | Sentence case |\n| constant | CONSTANT_CASE |\n| title    | Title Case    |\n\n\u003e [!NOTE]\n\u003e\n\u003e By attaching `OnlyAlphanumeric` to the end of each case modifier (e.g. `pascalOnlyAlphanumeric`), if the first character of the string is **not alphanumeric**, it is excluded and the case is converted.\n\u003e For example, `[projectId]` is converted to `ProjectId` with `pascalOnlyAlphanumeric`.\n\nThe content consists of headings and code blocks as follows.\n\n````md\n---\nactions:\n  - type: \"add\"\n    template: \"page.tsx\"\n---\n\n# page.tsx\n\n```tsx\nexport const Page = (children: { children: React.ReactNode }) =\u003e \u003cdiv\u003e{children}\u003c/div\u003e;\n```\n````\n\nAs mentioned earlier, the template of any element contained in actions needs to match the heading in the content.\nThe syntax of text/template can also be used for headings.\n\n## Benchmarks\n\n### Environment\n\n- OS: macOS Monterey 12.6.3\n- CPU: Apple M1 Max\n- Memory: 64GB\n- Node.js: 20.11.1\n- npm: 10.5.1\n\nWe measured the time it took to generate a simple React component with each package.\nThe benchmark project is available [here](./benchmarks).\n\n```tsx\nimport React from \"react\";\n\nexport const {{ name }}: React.FC = (children: { children: React.ReactNode }) =\u003e \u003cdiv\u003e{children}\u003c/div\u003e;\n```\n\n### Result\n\n| Package      | Version | Average time of 10 times(ms) |\n| ------------ | ------- | ---------------------------- |\n| plop         | 6.2.11  | 0.233                        |\n| scaffdog     | 3.0.0   | 0.385                        |\n| **moldable** | 0.0.4   | 0.182                        |\n\nMoldable is the fastest. This is because it is written in Go and executed by node after compiling it into a binary.\n\n## Third Party License\n\nParts of the code from the following projects have been borrowed and modified for use.\n\n- [Plop.js(MIT License)](https://github.com/plopjs/plop/blob/b797aafa8ae90adb59462114412505f9ec0c5bb1/LICENSE.md)\n- [Scaffdog(MIT License)](https://github.com/scaffdog/scaffdog/blob/9221585670365f67f6c439aea33a09ca79ae499c/LICENSE)\n- [eslint-interactive(MIT License)](https://github.com/mizdra/eslint-interactive/blob/a5ab787c4ccc780a2999b88d59d719cd6c1e651d/LICENSE)\n\nThe list of licenses is available at [THIRD_PARTY_LICENSE](https://github.com/CyberAgent/moldable/blob/main/THIRD_PARTY_LICENSE.md).\n\n## License\n\n[MIT License](./LICENSE)\n\n## Developers\n\n- Shuta Hirai - [GitHub](https://github.com/shuta13)\n- Satoshi Kotake - [GitHub](https://github.com/cotapon)\n- Takuma Shibuya - [GitHub](https://github.com/sivchari)\n\n## Copyright\n\nCyberAgent, Inc. All rights reserved.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcyberagent%2Fmoldable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcyberagent%2Fmoldable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcyberagent%2Fmoldable/lists"}