tools-template-cli 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +166 -25
- package/dist/index.js +46 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,17 +1,167 @@
|
|
|
1
1
|
# tmp-cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`tmp-cli` is a small CLI for cloning starter templates from this repository into a new project directory.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
### From npm
|
|
5
|
+
Install globally with your preferred package manager:
|
|
8
6
|
|
|
9
7
|
```bash
|
|
10
8
|
npm install -g tools-template-cli
|
|
9
|
+
pnpm add -g tools-template-cli
|
|
10
|
+
bun add -g tools-template-cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Then run:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
tmp-cli list
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Fastest way to create a project:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
tmp-cli create yuyi
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
That will show a template list, let you choose one, and then generate the project in `./yuyi`.
|
|
26
|
+
|
|
27
|
+
## What it does
|
|
28
|
+
|
|
29
|
+
- Lists the templates bundled with the package
|
|
30
|
+
- Copies a template into a new target directory
|
|
31
|
+
- Skips `.git`, `node_modules`, `.DS_Store`, and common build output directories
|
|
32
|
+
- Renames basic config values for JavaScript templates
|
|
33
|
+
- Optionally runs your package manager install step
|
|
34
|
+
- Optionally initializes a fresh git repository
|
|
35
|
+
|
|
36
|
+
## Available templates
|
|
37
|
+
|
|
38
|
+
Current templates:
|
|
39
|
+
|
|
40
|
+
- `supabase-expo-app`
|
|
41
|
+
- `supabase-user-management`
|
|
42
|
+
- `supabase-swiftui-app`
|
|
43
|
+
- `supabase_flutter_app`
|
|
44
|
+
|
|
45
|
+
Check the latest packaged list at any time:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
11
48
|
tmp-cli list
|
|
12
49
|
```
|
|
13
50
|
|
|
14
|
-
|
|
51
|
+
## Usage
|
|
52
|
+
|
|
53
|
+
Pass the target directory first and choose the template with a flag:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
tmp-cli create ./apps/mobile --template supabase-expo-app
|
|
57
|
+
tmp-cli create ./apps/admin --template supabase-user-management
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Or pass only the target directory and choose from the interactive template list:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
tmp-cli create yuyi
|
|
64
|
+
tmp-cli create ./apps/admin
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Initialize git in the generated project:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
tmp-cli create admin-app --template supabase-user-management --git
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Install dependencies immediately after generation:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
tmp-cli create my-mobile-app --template supabase-expo-app --install
|
|
77
|
+
tmp-cli create admin-app --template supabase-user-management --install
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Override the display name for supported templates:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
tmp-cli create my-mobile-app --template supabase-expo-app --name "My Mobile App"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Overwrite an existing non-empty target directory:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
tmp-cli create my-mobile-app --template supabase-expo-app --force
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Commands
|
|
93
|
+
|
|
94
|
+
### `tmp-cli list`
|
|
95
|
+
|
|
96
|
+
Prints all packaged templates.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
tmp-cli list
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### `tmp-cli create`
|
|
103
|
+
|
|
104
|
+
Create a project from one of the packaged templates.
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
tmp-cli create yuyi
|
|
108
|
+
tmp-cli create <target-directory> --template <template> [options]
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Options:
|
|
112
|
+
|
|
113
|
+
- `-t, --template <name>`: template name to copy
|
|
114
|
+
- `-n, --name <display-name>`: display name for supported templates
|
|
115
|
+
- `-p, --package-manager <tool>`: `npm`, `pnpm`, `yarn`, or `bun`
|
|
116
|
+
- `-f, --force`: overwrite a non-empty target directory
|
|
117
|
+
- `-i, --install`: run install after copy
|
|
118
|
+
- `-g, --git`: run `git init` in the generated directory
|
|
119
|
+
- `-h, --help`: show help
|
|
120
|
+
- `-v, --version`: show the CLI version
|
|
121
|
+
|
|
122
|
+
## Examples
|
|
123
|
+
|
|
124
|
+
Expo app:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
tmp-cli create my-mobile-app --template supabase-expo-app --name "My Mobile App"
|
|
128
|
+
cd my-mobile-app
|
|
129
|
+
npm install
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Next.js app:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
tmp-cli create admin-app --template supabase-user-management --git
|
|
136
|
+
cd admin-app
|
|
137
|
+
npm install
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Nested target directory:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
tmp-cli create ./apps/admin --template supabase-user-management --install
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Template behavior
|
|
147
|
+
|
|
148
|
+
These templates get automatic config renaming:
|
|
149
|
+
|
|
150
|
+
- `supabase-expo-app`
|
|
151
|
+
- `supabase-user-management`
|
|
152
|
+
|
|
153
|
+
That includes updates in files such as:
|
|
154
|
+
|
|
155
|
+
- `package.json`
|
|
156
|
+
- `package-lock.json`
|
|
157
|
+
- `app.json`
|
|
158
|
+
- `README.md`
|
|
159
|
+
|
|
160
|
+
The SwiftUI and Flutter templates are copied as-is apart from the target directory name and README reference.
|
|
161
|
+
|
|
162
|
+
## Local development
|
|
163
|
+
|
|
164
|
+
Use the local source directly while working on the CLI:
|
|
15
165
|
|
|
16
166
|
```bash
|
|
17
167
|
npm install
|
|
@@ -20,35 +170,26 @@ npm link
|
|
|
20
170
|
tmp-cli list
|
|
21
171
|
```
|
|
22
172
|
|
|
23
|
-
|
|
173
|
+
Or run the compiled output directly:
|
|
24
174
|
|
|
25
175
|
```bash
|
|
26
|
-
npm install
|
|
27
176
|
npm run build
|
|
28
|
-
node dist/index.js
|
|
29
|
-
node dist/index.js create supabase-expo-app my-mobile-app
|
|
30
|
-
node dist/index.js create ./apps/admin --template supabase-user-management --git
|
|
177
|
+
node dist/index.js help
|
|
31
178
|
```
|
|
32
179
|
|
|
33
|
-
##
|
|
180
|
+
## Install notes
|
|
34
181
|
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
- Renames basic config values for the JavaScript templates
|
|
39
|
-
- Optionally runs `npm install`, `pnpm install`, `yarn install`, or `bun install`
|
|
40
|
-
- Optionally initializes a fresh git repository in the generated project
|
|
182
|
+
- npm global install: `npm install -g tools-template-cli`
|
|
183
|
+
- pnpm global install: `pnpm add -g tools-template-cli`
|
|
184
|
+
- bun global install: `bun add -g tools-template-cli`
|
|
41
185
|
|
|
42
|
-
|
|
186
|
+
After installation, the command is always:
|
|
43
187
|
|
|
44
188
|
```bash
|
|
45
|
-
tmp-cli
|
|
46
|
-
tmp-cli create supabase-expo-app my-mobile-app
|
|
47
|
-
tmp-cli create ./apps/admin --template supabase-user-management --git
|
|
189
|
+
tmp-cli
|
|
48
190
|
```
|
|
49
191
|
|
|
50
|
-
##
|
|
192
|
+
## Package
|
|
51
193
|
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
- Use `node dist/index.js help` to see all options
|
|
194
|
+
- npm package: `tools-template-cli`
|
|
195
|
+
- global command: `tmp-cli`
|
package/dist/index.js
CHANGED
|
@@ -3,9 +3,10 @@ import { chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, readdirSy
|
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
4
|
import { basename, dirname, join, resolve } from "node:path";
|
|
5
5
|
import process from "node:process";
|
|
6
|
+
import { createInterface } from "node:readline/promises";
|
|
6
7
|
import { fileURLToPath } from "node:url";
|
|
7
8
|
import { getTemplate, templates } from "./templates.js";
|
|
8
|
-
const CLI_VERSION = "0.1.
|
|
9
|
+
const CLI_VERSION = "0.1.2";
|
|
9
10
|
const ROOT_DIR = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
10
11
|
const SKIP_NAMES = new Set([
|
|
11
12
|
".git",
|
|
@@ -23,7 +24,7 @@ const VALID_PACKAGE_MANAGERS = new Set([
|
|
|
23
24
|
"yarn",
|
|
24
25
|
"bun"
|
|
25
26
|
]);
|
|
26
|
-
function main() {
|
|
27
|
+
async function main() {
|
|
27
28
|
try {
|
|
28
29
|
const parsed = parseArgs(process.argv.slice(2));
|
|
29
30
|
if (hasBooleanFlag(parsed.flags, "help") || parsed.command === "help") {
|
|
@@ -39,7 +40,7 @@ function main() {
|
|
|
39
40
|
listTemplates();
|
|
40
41
|
return;
|
|
41
42
|
case "create":
|
|
42
|
-
createProject(resolveCreateOptions(parsed));
|
|
43
|
+
createProject(await resolveCreateOptions(parsed));
|
|
43
44
|
return;
|
|
44
45
|
default:
|
|
45
46
|
printHelp(`Unknown command: ${parsed.command}`);
|
|
@@ -107,19 +108,21 @@ function parseArgs(argv) {
|
|
|
107
108
|
}
|
|
108
109
|
return { command, positionals, flags };
|
|
109
110
|
}
|
|
110
|
-
function resolveCreateOptions(parsed) {
|
|
111
|
+
async function resolveCreateOptions(parsed) {
|
|
111
112
|
const templateFlag = getStringFlag(parsed.flags, "template");
|
|
112
113
|
const force = hasBooleanFlag(parsed.flags, "force");
|
|
113
114
|
const install = hasBooleanFlag(parsed.flags, "install");
|
|
114
115
|
const git = hasBooleanFlag(parsed.flags, "git");
|
|
115
116
|
let templateId = templateFlag;
|
|
116
|
-
let targetDirArg;
|
|
117
|
-
if (
|
|
118
|
-
|
|
117
|
+
let targetDirArg = parsed.positionals[0];
|
|
118
|
+
if (parsed.positionals.length === 0) {
|
|
119
|
+
throw new Error("Missing target directory for create command.");
|
|
120
|
+
}
|
|
121
|
+
if (parsed.positionals.length > 1) {
|
|
122
|
+
throw new Error("Use `tmp-cli create <target-directory>` or `tmp-cli create <target-directory> --template <name>`.");
|
|
119
123
|
}
|
|
120
|
-
|
|
121
|
-
templateId =
|
|
122
|
-
targetDirArg = parsed.positionals[1] ?? parsed.positionals[0];
|
|
124
|
+
if (!templateId) {
|
|
125
|
+
templateId = await promptForTemplateSelection();
|
|
123
126
|
}
|
|
124
127
|
if (!templateId) {
|
|
125
128
|
throw new Error("Missing template name. Run `tmp-cli list` to see available templates.");
|
|
@@ -128,9 +131,6 @@ function resolveCreateOptions(parsed) {
|
|
|
128
131
|
if (!template) {
|
|
129
132
|
throw new Error(`Unknown template "${templateId}". Run \`tmp-cli list\` to see available templates.`);
|
|
130
133
|
}
|
|
131
|
-
if (!targetDirArg) {
|
|
132
|
-
throw new Error("Missing target directory for create command.");
|
|
133
|
-
}
|
|
134
134
|
const targetDir = resolve(process.cwd(), targetDirArg);
|
|
135
135
|
const directoryName = basename(targetDir);
|
|
136
136
|
const displayName = getStringFlag(parsed.flags, "name") ?? directoryName;
|
|
@@ -153,6 +153,35 @@ function resolveCreateOptions(parsed) {
|
|
|
153
153
|
packageManager: packageManagerValue
|
|
154
154
|
};
|
|
155
155
|
}
|
|
156
|
+
async function promptForTemplateSelection() {
|
|
157
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
158
|
+
throw new Error("Template selection needs an interactive terminal. Pass --template <name> when running non-interactively.");
|
|
159
|
+
}
|
|
160
|
+
console.log("Choose a template:\n");
|
|
161
|
+
for (const [index, template] of templates.entries()) {
|
|
162
|
+
console.log(` ${index + 1}. ${template.id} - ${template.description} (${template.platform})`);
|
|
163
|
+
}
|
|
164
|
+
console.log("");
|
|
165
|
+
const readline = createInterface({
|
|
166
|
+
input: process.stdin,
|
|
167
|
+
output: process.stdout
|
|
168
|
+
});
|
|
169
|
+
try {
|
|
170
|
+
while (true) {
|
|
171
|
+
const answer = (await readline.question(`Template number [1-${templates.length}]: `)).trim();
|
|
172
|
+
const selectedIndex = Number.parseInt(answer, 10);
|
|
173
|
+
if (Number.isInteger(selectedIndex) &&
|
|
174
|
+
selectedIndex >= 1 &&
|
|
175
|
+
selectedIndex <= templates.length) {
|
|
176
|
+
return templates[selectedIndex - 1].id;
|
|
177
|
+
}
|
|
178
|
+
console.log(`Please enter a number between 1 and ${templates.length}.`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
finally {
|
|
182
|
+
readline.close();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
156
185
|
function createProject(options) {
|
|
157
186
|
const templateSourceDir = resolve(ROOT_DIR, options.template.path);
|
|
158
187
|
if (!existsSync(templateSourceDir)) {
|
|
@@ -357,7 +386,7 @@ function printHelp(errorMessage) {
|
|
|
357
386
|
|
|
358
387
|
Usage:
|
|
359
388
|
tmp-cli list
|
|
360
|
-
tmp-cli create <
|
|
389
|
+
tmp-cli create <target-directory>
|
|
361
390
|
tmp-cli create <target-directory> --template <template> [options]
|
|
362
391
|
|
|
363
392
|
Options:
|
|
@@ -371,10 +400,10 @@ Options:
|
|
|
371
400
|
-v, --version Show CLI version
|
|
372
401
|
|
|
373
402
|
Examples:
|
|
403
|
+
tmp-cli create yuyi
|
|
374
404
|
tmp-cli list
|
|
375
|
-
tmp-cli create supabase-expo-app my-mobile-app
|
|
376
405
|
tmp-cli create ./apps/admin --template supabase-user-management --git
|
|
377
|
-
tmp-cli create
|
|
406
|
+
tmp-cli create my-mobile-app --template supabase-expo-app --name "My Mobile App" --install
|
|
378
407
|
`);
|
|
379
408
|
}
|
|
380
|
-
main();
|
|
409
|
+
void main();
|