tangled
alpha
login
or
join now
dunkirk.sh
/
tacy-stack
0
fork
atom
the best lightweight web dev stack built on bun
0
fork
atom
overview
issues
pulls
pipelines
chore: add version to prompt
dunkirk.sh
3 months ago
1c570f1e
b219e256
verified
This commit was signed with the committer's
known signature
.
dunkirk.sh
SSH Key Fingerprint:
SHA256:DqcG0RXYExE26KiWo3VxJnsxswN1QNfTBvB+bdSpk80=
+135
-133
2 changed files
expand all
collapse all
unified
split
cli.ts
package.json
+134
-132
cli.ts
···
9
9
import { join } from "node:path";
10
10
import * as p from "@clack/prompts";
11
11
import { setTimeout } from "node:timers/promises";
12
12
+
import { version } from "./package.json";
12
13
13
14
async function main() {
14
14
-
console.clear();
15
15
-
16
16
-
p.intro("🥞 Tacy Stack Generator");
17
17
-
18
18
-
// Get project name
19
19
-
const projectName = await p.text({
20
20
-
message: "What is your project name?",
21
21
-
placeholder: "my-app",
22
22
-
validate(value) {
23
23
-
if (!value) return "Project name is required";
24
24
-
if (!/^[a-z0-9-_]+$/i.test(value)) {
25
25
-
return "Project name can only contain letters, numbers, hyphens, and underscores";
26
26
-
}
27
27
-
const targetDir = join(process.cwd(), value);
28
28
-
if (existsSync(targetDir)) {
29
29
-
return `Directory "${value}" already exists!`;
30
30
-
}
31
31
-
},
32
32
-
});
33
33
-
34
34
-
if (p.isCancel(projectName)) {
35
35
-
p.cancel("Operation cancelled");
36
36
-
process.exit(0);
37
37
-
}
38
38
-
39
39
-
const targetDir = join(process.cwd(), projectName as string);
40
40
-
const templateDir = import.meta.dir;
41
41
-
42
42
-
const s = p.spinner();
43
43
-
44
44
-
try {
45
45
-
// Create directory
46
46
-
s.start("Creating project directory");
47
47
-
mkdirSync(targetDir, { recursive: true });
48
48
-
await setTimeout(200);
49
49
-
s.stop("Created project directory");
50
50
-
51
51
-
// Copy template files
52
52
-
s.start("Copying template files");
53
53
-
await $`cp -r ${templateDir}/* ${targetDir}/`.quiet();
54
54
-
55
55
-
// Copy dotfiles explicitly
56
56
-
const dotfiles = [".env.example", ".gitignore", ".gitattributes"];
57
57
-
for (const dotfile of dotfiles) {
58
58
-
const source = join(templateDir, dotfile);
59
59
-
const dest = join(targetDir, dotfile);
60
60
-
if (existsSync(source)) {
61
61
-
await $`cp ${source} ${dest}`.quiet();
62
62
-
}
63
63
-
}
64
64
-
65
65
-
// Copy .github directory if it exists
66
66
-
const githubDir = join(templateDir, ".github");
67
67
-
if (existsSync(githubDir)) {
68
68
-
await $`cp -r ${githubDir} ${targetDir}/.github`.quiet();
69
69
-
}
70
70
-
71
71
-
await setTimeout(200);
72
72
-
s.stop("Copied template files");
73
73
-
74
74
-
// Remove CLI and template files
75
75
-
s.start("Cleaning up template files");
76
76
-
const filesToRemove = [
77
77
-
"cli.ts",
78
78
-
"TEMPLATE.md",
79
79
-
"TEMPLATE_SETUP_SUMMARY.md",
80
80
-
"CLI_SUMMARY.md",
81
81
-
"PUBLISHING.md",
82
82
-
"template.toml",
83
83
-
".github/TEMPLATE_SETUP.md",
84
84
-
];
85
85
-
86
86
-
for (const file of filesToRemove) {
87
87
-
const filePath = join(targetDir, file);
88
88
-
if (existsSync(filePath)) {
89
89
-
await $`rm -rf ${filePath}`.quiet();
90
90
-
}
91
91
-
}
92
92
-
await setTimeout(200);
93
93
-
s.stop("Cleaned up template files");
94
94
-
95
95
-
// Update package.json
96
96
-
s.start("Configuring package.json");
97
97
-
const packageJsonPath = join(targetDir, "package.json");
98
98
-
const packageJson = await Bun.file(packageJsonPath).json();
99
99
-
packageJson.name = projectName;
100
100
-
packageJson.version = "0.1.0";
101
101
-
delete packageJson.bin;
102
102
-
// Remove @clack/prompts from dependencies since it's only for the CLI
103
103
-
if (packageJson.dependencies?.["@clack/prompts"]) {
104
104
-
delete packageJson.dependencies["@clack/prompts"];
105
105
-
}
106
106
-
await Bun.write(packageJsonPath, JSON.stringify(packageJson, null, "\t") + "\n");
107
107
-
await setTimeout(200);
108
108
-
s.stop("Configured package.json");
109
109
-
110
110
-
// Initialize git
111
111
-
s.start("Initializing git repository");
112
112
-
await $`cd ${targetDir} && git init`.quiet();
113
113
-
await setTimeout(200);
114
114
-
s.stop("Initialized git repository");
115
115
-
116
116
-
// Create .env
117
117
-
s.start("Creating .env file");
118
118
-
await $`cd ${targetDir} && cp .env.example .env`.quiet();
119
119
-
await setTimeout(200);
120
120
-
s.stop("Created .env file");
121
121
-
122
122
-
// Install dependencies
123
123
-
s.start("Installing dependencies");
124
124
-
await $`cd ${targetDir} && bun install`.quiet();
125
125
-
s.stop("Installed dependencies");
126
126
-
127
127
-
// Setup database
128
128
-
s.start("Setting up database");
129
129
-
await $`cd ${targetDir} && bun run db:push`.quiet();
130
130
-
s.stop("Set up database");
131
131
-
132
132
-
} catch (error) {
133
133
-
s.stop("Failed");
134
134
-
p.cancel(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
135
135
-
process.exit(1);
136
136
-
}
137
137
-
138
138
-
p.outro("🎉 Project created successfully!");
139
139
-
140
140
-
p.note(
141
141
-
`cd ${projectName}\nbun dev`,
142
142
-
"Next steps"
143
143
-
);
15
15
+
console.clear();
16
16
+
17
17
+
p.intro(`🥞 Tacy Stack Generator @ ${version}`);
18
18
+
19
19
+
// Get project name
20
20
+
const projectName = await p.text({
21
21
+
message: "What is your project name?",
22
22
+
placeholder: "my-app",
23
23
+
validate(value) {
24
24
+
if (!value) return "Project name is required";
25
25
+
if (!/^[a-z0-9-_]+$/i.test(value)) {
26
26
+
return "Project name can only contain letters, numbers, hyphens, and underscores";
27
27
+
}
28
28
+
const targetDir = join(process.cwd(), value);
29
29
+
if (existsSync(targetDir)) {
30
30
+
return `Directory "${value}" already exists!`;
31
31
+
}
32
32
+
},
33
33
+
});
34
34
+
35
35
+
if (p.isCancel(projectName)) {
36
36
+
p.cancel("Operation cancelled");
37
37
+
process.exit(0);
38
38
+
}
39
39
+
40
40
+
const targetDir = join(process.cwd(), projectName as string);
41
41
+
const templateDir = import.meta.dir;
42
42
+
43
43
+
const s = p.spinner();
44
44
+
45
45
+
try {
46
46
+
// Create directory
47
47
+
s.start("Creating project directory");
48
48
+
mkdirSync(targetDir, { recursive: true });
49
49
+
await setTimeout(200);
50
50
+
s.stop("Created project directory");
51
51
+
52
52
+
// Copy template files
53
53
+
s.start("Copying template files");
54
54
+
await $`cp -r ${templateDir}/* ${targetDir}/`.quiet();
55
55
+
56
56
+
// Copy dotfiles explicitly
57
57
+
const dotfiles = [".env.example", ".gitignore", ".gitattributes"];
58
58
+
for (const dotfile of dotfiles) {
59
59
+
const source = join(templateDir, dotfile);
60
60
+
const dest = join(targetDir, dotfile);
61
61
+
if (existsSync(source)) {
62
62
+
await $`cp ${source} ${dest}`.quiet();
63
63
+
}
64
64
+
}
65
65
+
66
66
+
// Copy .github directory if it exists
67
67
+
const githubDir = join(templateDir, ".github");
68
68
+
if (existsSync(githubDir)) {
69
69
+
await $`cp -r ${githubDir} ${targetDir}/.github`.quiet();
70
70
+
}
71
71
+
72
72
+
await setTimeout(200);
73
73
+
s.stop("Copied template files");
74
74
+
75
75
+
// Remove CLI and template files
76
76
+
s.start("Cleaning up template files");
77
77
+
const filesToRemove = [
78
78
+
"cli.ts",
79
79
+
"TEMPLATE.md",
80
80
+
"TEMPLATE_SETUP_SUMMARY.md",
81
81
+
"CLI_SUMMARY.md",
82
82
+
"PUBLISHING.md",
83
83
+
"template.toml",
84
84
+
".github/TEMPLATE_SETUP.md",
85
85
+
];
86
86
+
87
87
+
for (const file of filesToRemove) {
88
88
+
const filePath = join(targetDir, file);
89
89
+
if (existsSync(filePath)) {
90
90
+
await $`rm -rf ${filePath}`.quiet();
91
91
+
}
92
92
+
}
93
93
+
await setTimeout(200);
94
94
+
s.stop("Cleaned up template files");
95
95
+
96
96
+
// Update package.json
97
97
+
s.start("Configuring package.json");
98
98
+
const packageJsonPath = join(targetDir, "package.json");
99
99
+
const packageJson = await Bun.file(packageJsonPath).json();
100
100
+
packageJson.name = projectName;
101
101
+
packageJson.version = "0.1.0";
102
102
+
delete packageJson.bin;
103
103
+
// Remove @clack/prompts from dependencies since it's only for the CLI
104
104
+
if (packageJson.dependencies?.["@clack/prompts"]) {
105
105
+
delete packageJson.dependencies["@clack/prompts"];
106
106
+
}
107
107
+
await Bun.write(
108
108
+
packageJsonPath,
109
109
+
JSON.stringify(packageJson, null, "\t") + "\n",
110
110
+
);
111
111
+
await setTimeout(200);
112
112
+
s.stop("Configured package.json");
113
113
+
114
114
+
// Initialize git
115
115
+
s.start("Initializing git repository");
116
116
+
await $`cd ${targetDir} && git init`.quiet();
117
117
+
await setTimeout(200);
118
118
+
s.stop("Initialized git repository");
119
119
+
120
120
+
// Create .env
121
121
+
s.start("Creating .env file");
122
122
+
await $`cd ${targetDir} && cp .env.example .env`.quiet();
123
123
+
await setTimeout(200);
124
124
+
s.stop("Created .env file");
125
125
+
126
126
+
// Install dependencies
127
127
+
s.start("Installing dependencies");
128
128
+
await $`cd ${targetDir} && bun install`.quiet();
129
129
+
s.stop("Installed dependencies");
130
130
+
131
131
+
// Setup database
132
132
+
s.start("Setting up database");
133
133
+
await $`cd ${targetDir} && bun run db:push`.quiet();
134
134
+
s.stop("Set up database");
135
135
+
} catch (error) {
136
136
+
s.stop("Failed");
137
137
+
p.cancel(
138
138
+
`Error: ${error instanceof Error ? error.message : "Unknown error"}`,
139
139
+
);
140
140
+
process.exit(1);
141
141
+
}
142
142
+
143
143
+
p.outro("🎉 Project created successfully!");
144
144
+
145
145
+
p.note(`cd ${projectName}\nbun dev`, "Next steps");
144
146
}
145
147
146
148
main().catch((error) => {
147
147
-
console.error(error);
148
148
-
process.exit(1);
149
149
+
console.error(error);
150
150
+
process.exit(1);
149
151
});
+1
-1
package.json
···
1
1
{
2
2
"name": "tacy-stack",
3
3
-
"version": "0.1.1",
3
3
+
"version": "0.1.2",
4
4
"module": "src/index.ts",
5
5
"type": "module",
6
6
"bin": {