|
16 | 16 | <a href="https://www.npmjs.com/package/create-gen-app"><img height="20" src="https://img.shields.io/github/package-json/v/hyperweb-io/dev-utils?filename=packages%2Fcreate-gen-app%2Fpackage.json"></a> |
17 | 17 | </p> |
18 | 18 |
|
19 | | -A TypeScript library for cloning and customizing template repositories with variable replacement. |
| 19 | +A TypeScript-first CLI/library for cloning template repositories, asking the user for variables, and generating a new project with sensible defaults. |
20 | 20 |
|
21 | 21 | ## Features |
22 | 22 |
|
23 | | -- Clone GitHub repositories or any git URL |
24 | | -- Extract template variables from filenames and file contents using `__VARIABLE__` syntax |
25 | | -- Load custom questions from `.questions.json` or `.questions.js` files |
26 | | -- Interactive prompts using inquirerer with CLI argument support |
27 | | -- Stream-based file processing for efficient variable replacement |
| 23 | +- Clone any Git repo (or GitHub `org/repo` shorthand) and optionally select a branch + subdirectory |
| 24 | +- Extract template variables from filenames and file contents using the safer `____VARIABLE____` convention |
| 25 | +- Merge auto-discovered variables with `.questions.{json,js}` (questions win, including `ignore` patterns) |
| 26 | +- Interactive prompts powered by `inquirerer`, with CLI flag overrides (`--VAR value`) and non-TTY mode for CI |
| 27 | +- Built-in CLI (`create-gen-app` / `cga`) that discovers templates, prompts once, and writes output safely |
| 28 | +- License scaffolding: choose from MIT, Apache-2.0, ISC, GPL-3.0, BSD-3-Clause, Unlicense, or MPL-2.0 and generate a populated `LICENSE` |
28 | 29 |
|
29 | 30 | ## Installation |
30 | 31 |
|
31 | 32 | ```bash |
32 | 33 | npm install create-gen-app |
| 34 | +# or for CLI only |
| 35 | +npm install -g create-gen-app |
33 | 36 | ``` |
34 | 37 |
|
35 | | -## Usage |
| 38 | +## CLI Usage |
36 | 39 |
|
37 | | -### Basic Usage |
| 40 | +```bash |
| 41 | +# interactively pick a template from launchql/pgpm-boilerplates |
| 42 | +create-gen-app --output ./workspace |
| 43 | + |
| 44 | +# short alias |
| 45 | +cga --template module --branch main --output ./module \ |
| 46 | + --USERFULLNAME "Jane Dev" --USEREMAIL [email protected] |
| 47 | + |
| 48 | +# point to a different repo/branch/path |
| 49 | +cga --repo github:my-org/my-templates --branch release \ |
| 50 | + --path ./templates --template api --output ./api |
| 51 | +``` |
| 52 | + |
| 53 | +Key flags: |
| 54 | + |
| 55 | +- `--repo`, `--branch`, `--path` – choose the Git repo, branch/tag, and subdirectory that contains templates |
| 56 | +- `--template` – folder inside `--path` (auto-prompted if omitted) |
| 57 | +- `--output` – destination directory (defaults to `./<template>`); use `--force` to overwrite |
| 58 | +- `--no-tty` – disable interactive prompts (ideal for CI) |
| 59 | +- `--version`, `--help` – standard metadata |
| 60 | +- Any extra `--VAR value` pairs become variable overrides |
| 61 | + |
| 62 | +## Library Usage |
38 | 63 |
|
39 | 64 | ```typescript |
40 | | -import { createGen } from 'create-gen-app'; |
| 65 | +import { createGen } from "create-gen-app"; |
41 | 66 |
|
42 | 67 | await createGen({ |
43 | | - templateUrl: 'https://github.com/user/template-repo', |
44 | | - outputDir: './my-new-project', |
| 68 | + templateUrl: "https://github.com/user/template-repo", |
| 69 | + fromBranch: "main", |
| 70 | + fromPath: "templates/module", |
| 71 | + outputDir: "./my-new-project", |
45 | 72 | argv: { |
46 | | - PROJECT_NAME: 'my-project', |
47 | | - AUTHOR: 'John Doe' |
48 | | - } |
| 73 | + USERFULLNAME: "Jane Dev", |
| 74 | + |
| 75 | + MODULENAME: "awesome-module", |
| 76 | + LICENSE: "MIT", |
| 77 | + }, |
| 78 | + noTty: true, |
49 | 79 | }); |
50 | 80 | ``` |
51 | 81 |
|
52 | 82 | ### Template Variables |
53 | 83 |
|
54 | | -Variables in your template should be wrapped in double underscores: |
| 84 | +Variables should be wrapped in four underscores on each side: |
55 | 85 |
|
56 | | -**Filename variables:** |
57 | 86 | ``` |
58 | | -__PROJECT_NAME__/ |
59 | | - __MODULE_NAME__.ts |
| 87 | +____PROJECT_NAME____/ |
| 88 | + src/____MODULE_NAME____.ts |
60 | 89 | ``` |
61 | 90 |
|
62 | | -**Content variables:** |
63 | 91 | ```typescript |
64 | | -// __MODULE_NAME__.ts |
65 | | -export const projectName = "__PROJECT_NAME__"; |
66 | | -export const author = "__AUTHOR__"; |
| 92 | +// ____MODULE_NAME____.ts |
| 93 | +export const projectName = "____PROJECT_NAME____"; |
| 94 | +export const author = "____USERFULLNAME____"; |
67 | 95 | ``` |
68 | 96 |
|
69 | | -### Custom Questions |
| 97 | +### Custom Questions & Ignore Rules |
70 | 98 |
|
71 | | -Create a `.questions.json` file in your template repository: |
| 99 | +Create a `.questions.json`: |
72 | 100 |
|
73 | 101 | ```json |
74 | 102 | { |
| 103 | + "ignore": ["__tests__", "docs/drafts"], |
75 | 104 | "questions": [ |
76 | 105 | { |
77 | | - "name": "PROJECT_NAME", |
| 106 | + "name": "____USERFULLNAME____", |
78 | 107 | "type": "text", |
79 | | - "message": "What is your project name?", |
| 108 | + "message": "Enter author full name", |
80 | 109 | "required": true |
81 | 110 | }, |
82 | 111 | { |
83 | | - "name": "AUTHOR", |
84 | | - "type": "text", |
85 | | - "message": "Who is the author?" |
| 112 | + "name": "____LICENSE____", |
| 113 | + "type": "list", |
| 114 | + "message": "Choose a license", |
| 115 | + "options": ["MIT", "Apache-2.0", "ISC", "GPL-3.0"] |
86 | 116 | } |
87 | 117 | ] |
88 | 118 | } |
89 | 119 | ``` |
90 | 120 |
|
91 | | -Or use `.questions.js` for dynamic questions: |
92 | | - |
93 | | -```javascript |
94 | | -/** |
95 | | - * @typedef {Object} Questions |
96 | | - * @property {Array} questions - Array of question objects |
97 | | - */ |
98 | | - |
99 | | -module.exports = { |
100 | | - questions: [ |
101 | | - { |
102 | | - name: 'PROJECT_NAME', |
103 | | - type: 'text', |
104 | | - message: 'What is your project name?', |
105 | | - required: true |
106 | | - } |
107 | | - ] |
108 | | -}; |
109 | | -``` |
110 | | - |
111 | | -## API |
112 | | - |
113 | | -### `createGen(options: CreateGenOptions): Promise<string>` |
114 | | - |
115 | | -Main function to create a project from a template. |
116 | | - |
117 | | -**Options:** |
118 | | -- `templateUrl` (string): URL or path to the template repository |
119 | | -- `outputDir` (string): Destination directory for the generated project |
120 | | -- `argv` (Record<string, any>): Command-line arguments to pre-populate answers |
121 | | -- `noTty` (boolean): Whether to disable TTY mode for non-interactive usage |
122 | | - |
123 | | -### `extractVariables(templateDir: string): Promise<ExtractedVariables>` |
124 | | - |
125 | | -Extract all variables from a template directory. |
| 121 | +Or `.questions.js` for dynamic logic. Question names can use `____VAR____` or plain `VAR`; they'll be normalized automatically. |
126 | 122 |
|
127 | | -### `promptUser(extractedVariables: ExtractedVariables, argv?: Record<string, any>, noTty?: boolean): Promise<Record<string, any>>` |
| 123 | +### License Templates |
128 | 124 |
|
129 | | -Prompt the user for variable values using inquirerer. |
| 125 | +`create-gen-app` ships text templates in `licenses-templates/`. To add another license, drop a `.txt` file matching the desired key (e.g., `BSD-2-CLAUSE.txt`) with placeholders: |
130 | 126 |
|
131 | | -### `replaceVariables(templateDir: string, outputDir: string, extractedVariables: ExtractedVariables, answers: Record<string, any>): Promise<void>` |
| 127 | +- `{{YEAR}}`, `{{AUTHOR}}`, `{{EMAIL_LINE}}` |
132 | 128 |
|
133 | | -Replace variables in all files and filenames. |
| 129 | +No code changes are needed; the CLI discovers templates at runtime and will warn if a `.questions` option doesn’t have a matching template. |
134 | 130 |
|
135 | | -## Variable Naming Rules |
| 131 | +## API Overview |
136 | 132 |
|
137 | | -Variables can contain: |
138 | | -- Letters (a-z, A-Z) |
139 | | -- Numbers (0-9) |
140 | | -- Underscores (_) |
141 | | -- Must start with a letter or underscore |
| 133 | +- `createGen(options)` – full pipeline (clone → extract → prompt → replace) |
| 134 | +- `cloneRepo(url, { branch })` – clone to a temp dir |
| 135 | +- `extractVariables(dir)` – parse file/folder names + content for variables, load `.questions` |
| 136 | +- `promptUser(extracted, argv, noTty)` – run interactive questions with CLI overrides and alias deduping |
| 137 | +- `replaceVariables(templateDir, outputDir, extracted, answers)` – copy files, rename paths, render licenses |
142 | 138 |
|
143 | | -Examples of valid variables: |
144 | | -- `__PROJECT_NAME__` |
145 | | -- `__author__` |
146 | | -- `__CamelCase__` |
147 | | -- `__snake_case__` |
148 | | -- `__VERSION_1__` |
| 139 | +See `dev/README.md` for the local development helper script (`pnpm dev`). |
0 commit comments