gosetup 0.1.0
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 +15 -0
- package/bin/gosetup +0 -0
- package/package.json +39 -0
- package/src/index.tsx +189 -0
- package/src/utils/data.ts +289 -0
- package/src/utils/types.ts +12 -0
- package/src/utils/utils.ts +32 -0
package/README.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# react
|
|
2
|
+
|
|
3
|
+
To install dependencies:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
bun install
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
To run:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
bun dev
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
This project was created using `bun create tui`. [create-tui](https://git.new/create-tui) is the easiest way to get started with OpenTUI.
|
package/bin/gosetup
ADDED
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gosetup",
|
|
3
|
+
"module": "src/index.tsx",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"description": "TUI for scaffolding Go backend projects",
|
|
6
|
+
"author": "divin3circle",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://github.com/divin3circle/gosetup",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/divin3circle/gosetup.git"
|
|
12
|
+
},
|
|
13
|
+
"bin": {
|
|
14
|
+
"gosetup": "./bin/gosetup"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"scripts": {
|
|
18
|
+
"dev": "bun run --watch src/index.tsx",
|
|
19
|
+
"build": "bun build src/index.tsx --compile --outfile ./bin/gosetup && chmod +x ./bin/gosetup",
|
|
20
|
+
"prepublishOnly": "bun run build"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"bin",
|
|
24
|
+
"src",
|
|
25
|
+
"package.json",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/bun": "latest"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"typescript": "^5"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@opentui/core": "^0.1.69",
|
|
36
|
+
"@opentui/react": "^0.1.69",
|
|
37
|
+
"react": "^19.2.3"
|
|
38
|
+
}
|
|
39
|
+
}
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { createCliRenderer, RGBA, TextAttributes } from "@opentui/core";
|
|
4
|
+
import { createRoot } from "@opentui/react";
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
import { useKeyboard } from "@opentui/react";
|
|
7
|
+
import { $ } from "bun";
|
|
8
|
+
import { createDirectoryStructure, Mode } from "./utils/utils";
|
|
9
|
+
import { RootDirectory } from "./utils/data";
|
|
10
|
+
|
|
11
|
+
enum Screen {
|
|
12
|
+
Welcome,
|
|
13
|
+
Username,
|
|
14
|
+
Form,
|
|
15
|
+
Success,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function App() {
|
|
19
|
+
const [screen, setScreen] = useState(Screen.Welcome);
|
|
20
|
+
const [projectName, setProjectName] = useState("");
|
|
21
|
+
const [githubUsername, setGithubUsername] = useState("");
|
|
22
|
+
const [status, setStatus] = useState("");
|
|
23
|
+
const [loading, setLoading] = useState(false);
|
|
24
|
+
|
|
25
|
+
useKeyboard((key) => {
|
|
26
|
+
if (screen === Screen.Welcome && key.name === "return") {
|
|
27
|
+
setScreen(Screen.Username);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
useKeyboard((key) => {
|
|
32
|
+
if (key.name === "escape") {
|
|
33
|
+
switch (screen) {
|
|
34
|
+
case Screen.Username:
|
|
35
|
+
setScreen(Screen.Welcome);
|
|
36
|
+
break;
|
|
37
|
+
case Screen.Form:
|
|
38
|
+
setScreen(Screen.Username);
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const handleSubmit = async (value: string) => {
|
|
45
|
+
if (!value.trim()) {
|
|
46
|
+
setStatus("Project name is required.");
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (!githubUsername.trim()) {
|
|
50
|
+
setStatus("GitHub username is required.");
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
setStatus("Creating project...");
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
setLoading(true);
|
|
58
|
+
const name = value.trim();
|
|
59
|
+
|
|
60
|
+
const isCurrentDir = name === ".";
|
|
61
|
+
|
|
62
|
+
let targetPath: string;
|
|
63
|
+
let moduleName: string;
|
|
64
|
+
|
|
65
|
+
if (isCurrentDir) {
|
|
66
|
+
targetPath = ".";
|
|
67
|
+
|
|
68
|
+
const cwd = process.cwd();
|
|
69
|
+
moduleName = cwd.split("/").pop() || "app";
|
|
70
|
+
} else {
|
|
71
|
+
targetPath = name;
|
|
72
|
+
moduleName = name;
|
|
73
|
+
await $`mkdir -p ${targetPath}`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
await $`cd ${targetPath} && go mod init github.com/${githubUsername}/${moduleName}`;
|
|
77
|
+
|
|
78
|
+
await createDirectoryStructure(RootDirectory, targetPath);
|
|
79
|
+
|
|
80
|
+
await $`cd ${targetPath} && go mod tidy`;
|
|
81
|
+
|
|
82
|
+
setLoading(false);
|
|
83
|
+
|
|
84
|
+
if (isCurrentDir) {
|
|
85
|
+
setStatus(
|
|
86
|
+
`Project "${moduleName}" created successfully in current directory`
|
|
87
|
+
);
|
|
88
|
+
} else {
|
|
89
|
+
setStatus(`Project "${name}" created successfully in ./${name}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
setScreen(Screen.Success);
|
|
93
|
+
} catch (error: any) {
|
|
94
|
+
setLoading(false);
|
|
95
|
+
setStatus(`Error: ${error.message}`);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<box
|
|
101
|
+
flexGrow={1}
|
|
102
|
+
alignItems="center"
|
|
103
|
+
justifyContent="center"
|
|
104
|
+
backgroundColor={RGBA.fromHex(Mode.DARK)}
|
|
105
|
+
>
|
|
106
|
+
{screen === Screen.Welcome && (
|
|
107
|
+
<box flexDirection="column" alignItems="center">
|
|
108
|
+
<ascii-font
|
|
109
|
+
font="tiny"
|
|
110
|
+
text="Go Setup"
|
|
111
|
+
color={RGBA.fromHex(Mode.LIGHT)}
|
|
112
|
+
/>
|
|
113
|
+
<text
|
|
114
|
+
attributes={TextAttributes.DIM | TextAttributes.BOLD}
|
|
115
|
+
marginTop={1}
|
|
116
|
+
>
|
|
117
|
+
Welcome to Go Backend Setup.
|
|
118
|
+
</text>
|
|
119
|
+
<text attributes={TextAttributes.BOLD} marginTop={2} fg="#ff6e58">
|
|
120
|
+
Press Enter to start
|
|
121
|
+
</text>
|
|
122
|
+
</box>
|
|
123
|
+
)}
|
|
124
|
+
|
|
125
|
+
{screen === Screen.Username && (
|
|
126
|
+
<box flexDirection="column" alignItems="center" width={50}>
|
|
127
|
+
<text
|
|
128
|
+
attributes={TextAttributes.DIM | TextAttributes.BOLD}
|
|
129
|
+
marginBottom={1}
|
|
130
|
+
>
|
|
131
|
+
Enter GitHub Username:
|
|
132
|
+
</text>
|
|
133
|
+
<input
|
|
134
|
+
value={githubUsername}
|
|
135
|
+
onChange={setGithubUsername}
|
|
136
|
+
onSubmit={() => setScreen(Screen.Form)}
|
|
137
|
+
placeholder="your-github-username"
|
|
138
|
+
focused
|
|
139
|
+
width="100%"
|
|
140
|
+
backgroundColor={RGBA.fromHex("#020202")}
|
|
141
|
+
/>
|
|
142
|
+
<text attributes={TextAttributes.DIM} marginTop={4}>
|
|
143
|
+
[Esc to go back]
|
|
144
|
+
</text>
|
|
145
|
+
</box>
|
|
146
|
+
)}
|
|
147
|
+
|
|
148
|
+
{screen === Screen.Form && (
|
|
149
|
+
<box flexDirection="column" alignItems="center" width={50}>
|
|
150
|
+
<text attributes={TextAttributes.DIM} marginBottom={1}>
|
|
151
|
+
Enter Project Name:
|
|
152
|
+
</text>
|
|
153
|
+
<input
|
|
154
|
+
value={projectName}
|
|
155
|
+
onChange={setProjectName}
|
|
156
|
+
onSubmit={handleSubmit}
|
|
157
|
+
placeholder="my-go-app"
|
|
158
|
+
focused
|
|
159
|
+
width="100%"
|
|
160
|
+
backgroundColor={RGBA.fromHex("#020202")}
|
|
161
|
+
/>
|
|
162
|
+
<text attributes={TextAttributes.DIM} marginTop={4}>
|
|
163
|
+
[Esc to go back]
|
|
164
|
+
</text>
|
|
165
|
+
</box>
|
|
166
|
+
)}
|
|
167
|
+
|
|
168
|
+
{screen === Screen.Success && (
|
|
169
|
+
<box flexDirection="column" alignItems="center">
|
|
170
|
+
<ascii-font text="Success!" font="tiny" />
|
|
171
|
+
<text marginTop={6} fg={RGBA.fromHex("#95f764")}>
|
|
172
|
+
{status}
|
|
173
|
+
</text>
|
|
174
|
+
<text marginTop={2}>Press Ctrl+C to exit.</text>
|
|
175
|
+
</box>
|
|
176
|
+
)}
|
|
177
|
+
</box>
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async function main() {
|
|
182
|
+
const renderer = await createCliRenderer({
|
|
183
|
+
exitOnCtrlC: true,
|
|
184
|
+
});
|
|
185
|
+
createRoot(renderer).render(<App />);
|
|
186
|
+
renderer.start();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import type { IDirectory, IFile } from "./types";
|
|
2
|
+
|
|
3
|
+
const envLocalFile: IFile = {
|
|
4
|
+
name: ".env.local",
|
|
5
|
+
content: `# Environment variables
|
|
6
|
+
PORT=
|
|
7
|
+
POSTGRES_DB=
|
|
8
|
+
POSTGRES_USER=
|
|
9
|
+
POSTGRES_PASSWORD=
|
|
10
|
+
DB_URL=
|
|
11
|
+
TEST_DB_URL=
|
|
12
|
+
PRODUCTION_DB_URL=
|
|
13
|
+
`,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const gitignoreFile: IFile = {
|
|
17
|
+
name: ".gitignore",
|
|
18
|
+
content: `# Add more as needed
|
|
19
|
+
/database
|
|
20
|
+
./database`,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const readmeFile: IFile = {
|
|
24
|
+
name: "README.md",
|
|
25
|
+
content: `# Go Setup Project
|
|
26
|
+
This is a Go project scaffolded using Go Setup.
|
|
27
|
+
|
|
28
|
+
## Setup Instructions
|
|
29
|
+
1. Ensure you have Go installed on your machine.
|
|
30
|
+
2. Navigate to the project directory.
|
|
31
|
+
3. Run \`go mod tidy\` to install dependencies.
|
|
32
|
+
|
|
33
|
+
## Project Structure
|
|
34
|
+
- \`internal/\`: Contains internal application code.
|
|
35
|
+
- \`migrations/\`: Database migration files.
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
- To run the application, use \`go run main.go\`.
|
|
39
|
+
|
|
40
|
+
## License
|
|
41
|
+
This project is licensed under the MIT License.
|
|
42
|
+
`,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const mainGoFile: IFile = {
|
|
46
|
+
name: "main.go",
|
|
47
|
+
content: `package main
|
|
48
|
+
import "fmt"
|
|
49
|
+
|
|
50
|
+
func main() {
|
|
51
|
+
fmt.Println("Hello, Go Setup!")
|
|
52
|
+
}
|
|
53
|
+
`,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const dockerfile: IFile = {
|
|
57
|
+
name: "Dockerfile",
|
|
58
|
+
content: `# Use the official Golang image as a base image
|
|
59
|
+
# Build stage
|
|
60
|
+
FROM golang:1.24-alpine AS builder
|
|
61
|
+
|
|
62
|
+
WORKDIR /app
|
|
63
|
+
|
|
64
|
+
# Copy go mod files
|
|
65
|
+
COPY go.mod go.sum ./
|
|
66
|
+
RUN go mod download
|
|
67
|
+
|
|
68
|
+
# Copy source code
|
|
69
|
+
COPY . .
|
|
70
|
+
|
|
71
|
+
# Build the application
|
|
72
|
+
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
|
|
73
|
+
|
|
74
|
+
# Production stage
|
|
75
|
+
FROM alpine:latest
|
|
76
|
+
|
|
77
|
+
RUN apk --no-cache add ca-certificates
|
|
78
|
+
|
|
79
|
+
WORKDIR /root/
|
|
80
|
+
|
|
81
|
+
# Copy the binary from builder
|
|
82
|
+
COPY --from=builder /app/main .
|
|
83
|
+
COPY --from=builder /app/migrations ./migrations
|
|
84
|
+
|
|
85
|
+
EXPOSE 8080
|
|
86
|
+
|
|
87
|
+
CMD ["./main"]
|
|
88
|
+
`,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const dockerComposeFile: IFile = {
|
|
92
|
+
name: "docker-compose.yml",
|
|
93
|
+
content: `
|
|
94
|
+
version: "3.8"
|
|
95
|
+
|
|
96
|
+
services:
|
|
97
|
+
db:
|
|
98
|
+
container_name: "db"
|
|
99
|
+
image: postgres:12.4-alpine
|
|
100
|
+
volumes:
|
|
101
|
+
- "./database/postgres-data:/var/lib/postgresql/data:rw"
|
|
102
|
+
ports:
|
|
103
|
+
- "5432:5432"
|
|
104
|
+
environment:
|
|
105
|
+
POSTGRES_DB: postgres
|
|
106
|
+
POSTGRES_USER: postgres
|
|
107
|
+
POSTGRES_PASSWORD: postgres
|
|
108
|
+
restart: unless-stopped
|
|
109
|
+
test_db:
|
|
110
|
+
container_name: "test_db"
|
|
111
|
+
image: postgres:12.4-alpine
|
|
112
|
+
volumes:
|
|
113
|
+
- "./database/postgres-test-data:/var/lib/postgresql/data:rw"
|
|
114
|
+
ports:
|
|
115
|
+
- "5433:5432"
|
|
116
|
+
environment:
|
|
117
|
+
POSTGRES_DB: postgres
|
|
118
|
+
POSTGRES_USER: postgres
|
|
119
|
+
POSTGRES_PASSWORD: postgres
|
|
120
|
+
restart: unless-stopped
|
|
121
|
+
`,
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const userHandlerFile: IFile = {
|
|
125
|
+
name: "user_handler.go",
|
|
126
|
+
content: `package api`,
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const tokenHandlerFile: IFile = {
|
|
130
|
+
name: "token_handler.go",
|
|
131
|
+
content: `package api`,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const appFile: IFile = {
|
|
135
|
+
name: "app.go",
|
|
136
|
+
content: `package app`,
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const middlewareFile: IFile = {
|
|
140
|
+
name: "middleware.go",
|
|
141
|
+
content: `package middleware`,
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const utilsFile: IFile = {
|
|
145
|
+
name: "utils.go",
|
|
146
|
+
content: `package utils`,
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const tokenFile: IFile = {
|
|
150
|
+
name: "token.go",
|
|
151
|
+
content: `package tokens`,
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const routesFile: IFile = {
|
|
155
|
+
name: "routes.go",
|
|
156
|
+
content: `package routes`,
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const storeFile: IFile = {
|
|
160
|
+
name: "db.go",
|
|
161
|
+
content: `package stores`,
|
|
162
|
+
};
|
|
163
|
+
const userStoreFile: IFile = {
|
|
164
|
+
name: "user_store.go",
|
|
165
|
+
content: `package stores`,
|
|
166
|
+
};
|
|
167
|
+
const tokenStoreFile: IFile = {
|
|
168
|
+
name: "token_store.go",
|
|
169
|
+
content: `package stores`,
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const userMigrationFile: IFile = {
|
|
173
|
+
name: "00001_users.sql",
|
|
174
|
+
content: `
|
|
175
|
+
-- +goose Up
|
|
176
|
+
-- +goose StatementBegin
|
|
177
|
+
|
|
178
|
+
-- Enable UUID extension for gen_random_uuid()
|
|
179
|
+
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
|
180
|
+
|
|
181
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
182
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
183
|
+
username VARCHAR(50),
|
|
184
|
+
mobile_number VARCHAR(13),
|
|
185
|
+
hashed_password VARCHAR(255),
|
|
186
|
+
account_id VARCHAR(100),
|
|
187
|
+
profile_image_url VARCHAR(2048),
|
|
188
|
+
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
|
189
|
+
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
|
190
|
+
deleted_at TIMESTAMPTZ
|
|
191
|
+
);
|
|
192
|
+
-- +goose StatementEnd
|
|
193
|
+
|
|
194
|
+
-- +goose Down
|
|
195
|
+
-- +goose StatementBegin
|
|
196
|
+
DROP TABLE IF EXISTS users;
|
|
197
|
+
-- +goose StatementEnd
|
|
198
|
+
`,
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const tokenMigrationFile: IFile = {
|
|
202
|
+
name: "00002_tokens.sql",
|
|
203
|
+
content: `
|
|
204
|
+
-- +goose Up
|
|
205
|
+
-- +goose StatementBegin
|
|
206
|
+
CREATE TABLE IF NOT EXISTS tokens (
|
|
207
|
+
hash BYTEA PRIMARY KEY,
|
|
208
|
+
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
209
|
+
merchant_id UUID NOT NULL REFERENCES merchants(id) ON DELETE CASCADE,
|
|
210
|
+
expiry TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
211
|
+
scope VARCHAR(255) NOT NULL
|
|
212
|
+
)
|
|
213
|
+
-- +goose StatementEnd
|
|
214
|
+
|
|
215
|
+
-- +goose Down
|
|
216
|
+
-- +goose StatementBegin
|
|
217
|
+
DROP TABLE tokens;
|
|
218
|
+
-- +goose StatementEnd
|
|
219
|
+
`,
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const fsMigrationFile: IFile = {
|
|
223
|
+
name: "fs.go",
|
|
224
|
+
content: `package migrations
|
|
225
|
+
|
|
226
|
+
import (
|
|
227
|
+
"embed"
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
//go:embed *.sql
|
|
231
|
+
var FS embed.FS`,
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const internalDirectories: IDirectory[] = [
|
|
235
|
+
{
|
|
236
|
+
name: "api",
|
|
237
|
+
files: [userHandlerFile, tokenHandlerFile],
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
name: "app",
|
|
241
|
+
files: [appFile],
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
name: "middleware",
|
|
245
|
+
files: [middlewareFile],
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
name: "utils",
|
|
249
|
+
files: [utilsFile],
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
name: "tokens",
|
|
253
|
+
files: [tokenFile],
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
name: "routes",
|
|
257
|
+
files: [routesFile],
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
name: "stores",
|
|
261
|
+
files: [storeFile, userStoreFile, tokenStoreFile],
|
|
262
|
+
},
|
|
263
|
+
];
|
|
264
|
+
|
|
265
|
+
const internalDirectory: IDirectory = {
|
|
266
|
+
name: "internal",
|
|
267
|
+
subdirectories: internalDirectories,
|
|
268
|
+
files: [],
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
const migrationsDirectory: IDirectory = {
|
|
272
|
+
name: "migrations",
|
|
273
|
+
files: [fsMigrationFile, userMigrationFile, tokenMigrationFile],
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
const RootFiles: IFile[] = [
|
|
277
|
+
readmeFile,
|
|
278
|
+
gitignoreFile,
|
|
279
|
+
mainGoFile,
|
|
280
|
+
envLocalFile,
|
|
281
|
+
dockerfile,
|
|
282
|
+
dockerComposeFile,
|
|
283
|
+
];
|
|
284
|
+
|
|
285
|
+
export const RootDirectory: IDirectory = {
|
|
286
|
+
name: ".",
|
|
287
|
+
subdirectories: [migrationsDirectory, internalDirectory],
|
|
288
|
+
files: RootFiles,
|
|
289
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { $ } from "bun";
|
|
2
|
+
import type { IDirectory } from "./types";
|
|
3
|
+
|
|
4
|
+
export enum Mode {
|
|
5
|
+
LIGHT = "#fef7f7",
|
|
6
|
+
DARK = "#020202",
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function createDirectoryStructure(
|
|
10
|
+
directory: IDirectory,
|
|
11
|
+
basePath: string
|
|
12
|
+
): Promise<void> {
|
|
13
|
+
const currentPath =
|
|
14
|
+
directory.name === "." ? basePath : `${basePath}/${directory.name}`;
|
|
15
|
+
|
|
16
|
+
if (directory.name !== ".") {
|
|
17
|
+
await $`mkdir -p ${currentPath}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (directory.files && directory.files.length > 0) {
|
|
21
|
+
for (const file of directory.files) {
|
|
22
|
+
const filePath = `${currentPath}/${file.name}`;
|
|
23
|
+
await Bun.write(filePath, file.content ?? "");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (directory.subdirectories && directory.subdirectories.length > 0) {
|
|
28
|
+
for (const subdir of directory.subdirectories) {
|
|
29
|
+
await createDirectoryStructure(subdir, currentPath);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|