scaffy-tool 0.2.0 → 1.0.1
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 +21 -26
- package/cli.js +18 -41
- package/core/detector.js +5 -31
- package/core/executor.js +5 -27
- package/core/interviewer.js +15 -19
- package/core/plugin-validator.js +1 -1
- package/core/registry.js +47 -28
- package/core/utils.js +2 -19
- package/package.json +11 -11
- package/registry/go/gin/plugin.json +23 -0
- package/registry/go/gin/v1/questions.js +19 -0
- package/registry/go/gin/v1/scaffold.js +196 -0
- package/registry/index.json +4 -4
- package/registry/javascript/expressjs/plugin.json +44 -0
- package/registry/javascript/expressjs/v4/questions.js +43 -0
- package/registry/javascript/expressjs/v4/scaffold.js +236 -0
- package/registry/javascript/nestjs/plugin.json +2 -2
- package/registry/javascript/nestjs/v10/questions.js +6 -4
- package/registry/javascript/nestjs/v10/scaffold.js +1 -1
- package/registry/javascript/nestjs/v11/questions.js +61 -0
- package/registry/javascript/nestjs/v11/scaffold.js +94 -0
- package/registry/javascript/nextjs/plugin.json +44 -0
- package/registry/javascript/nextjs/v14/questions.js +44 -0
- package/registry/javascript/nextjs/v14/scaffold.js +57 -0
- package/registry/javascript/vuejs/v3/questions.js +5 -3
- package/registry/javascript/vuejs/v3/scaffold.js +3 -10
- package/registry/php/laravel/plugin.json +2 -2
- package/registry/php/laravel/v11/questions.js +3 -3
- package/registry/php/laravel/v11/scaffold.js +1 -1
- package/registry/php/laravel/v12/questions.js +45 -0
- package/registry/php/laravel/v12/scaffold.js +46 -0
- package/registry/php/laravel/v13/questions.js +28 -0
- package/registry/php/laravel/v13/scaffold.js +46 -0
- package/registry/php/laravel/v13/test/.gitkeep +0 -0
- package/registry/php/laravel/v13/test/questions.test.js +48 -0
- package/registry/php/laravel/v13/test/scaffold.test.js +105 -0
- package/registry/php/symfony/plugin.json +35 -0
- package/registry/php/symfony/v7/questions.js +19 -0
- package/registry/php/symfony/v7/scaffold.js +74 -0
- package/registry/python/django/plugin.json +35 -0
- package/registry/python/django/v5/questions.js +24 -0
- package/registry/python/django/v5/scaffold.js +107 -0
- package/registry/python/fastapi/plugin.json +35 -0
- package/registry/python/fastapi/v1/questions.js +25 -0
- package/registry/python/fastapi/v1/scaffold.js +180 -0
package/core/registry.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { createRequire } from 'module';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
4
10
|
|
|
5
11
|
const REGISTRY_PATH = path.join(__dirname, '..', 'registry');
|
|
6
12
|
const INDEX_PATH = path.join(REGISTRY_PATH, 'index.json');
|
|
@@ -23,11 +29,21 @@ const getFrameworks = () => {
|
|
|
23
29
|
return index.frameworks;
|
|
24
30
|
};
|
|
25
31
|
|
|
32
|
+
const isPluginComplete = framework => {
|
|
33
|
+
const pluginPath = path.join(REGISTRY_PATH, framework.path);
|
|
34
|
+
const versionPath = path.join(pluginPath, framework.latest);
|
|
35
|
+
return (
|
|
36
|
+
fs.existsSync(path.join(versionPath, 'questions.js')) &&
|
|
37
|
+
fs.existsSync(path.join(versionPath, 'scaffold.js'))
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const getAvailableFrameworks = () => getFrameworks().filter(isPluginComplete);
|
|
42
|
+
|
|
26
43
|
const findFramework = query => {
|
|
27
44
|
const q = query.toLowerCase().trim();
|
|
28
|
-
|
|
29
45
|
return (
|
|
30
|
-
|
|
46
|
+
getAvailableFrameworks().find(
|
|
31
47
|
f =>
|
|
32
48
|
f.name.toLowerCase() === q || f.alias.some(a => a.toLowerCase() === q)
|
|
33
49
|
) || null
|
|
@@ -36,8 +52,7 @@ const findFramework = query => {
|
|
|
36
52
|
|
|
37
53
|
const searchFrameworks = query => {
|
|
38
54
|
const q = query.toLowerCase().trim();
|
|
39
|
-
|
|
40
|
-
return getFrameworks().filter(
|
|
55
|
+
return getAvailableFrameworks().filter(
|
|
41
56
|
f =>
|
|
42
57
|
f.name.toLowerCase().includes(q) ||
|
|
43
58
|
f.language.toLowerCase().includes(q) ||
|
|
@@ -56,58 +71,60 @@ const groupByLanguage = frameworks =>
|
|
|
56
71
|
|
|
57
72
|
const validatePluginFiles = (pluginPath, version) => {
|
|
58
73
|
const versionPath = path.join(pluginPath, version);
|
|
59
|
-
|
|
60
74
|
const requiredFiles = [
|
|
61
75
|
{ path: path.join(pluginPath, 'plugin.json'), name: 'plugin.json' },
|
|
62
76
|
{ path: path.join(versionPath, 'questions.js'), name: 'questions.js' },
|
|
63
77
|
{ path: path.join(versionPath, 'scaffold.js'), name: 'scaffold.js' },
|
|
64
78
|
];
|
|
65
|
-
|
|
66
79
|
const missing = requiredFiles
|
|
67
80
|
.filter(f => !fs.existsSync(f.path))
|
|
68
81
|
.map(f => f.name);
|
|
69
|
-
|
|
70
82
|
return {
|
|
71
83
|
valid: missing.length === 0,
|
|
72
84
|
missing,
|
|
73
85
|
};
|
|
74
86
|
};
|
|
75
87
|
|
|
76
|
-
const loadPlugin = (framework, version) => {
|
|
88
|
+
const loadPlugin = async (framework, version) => {
|
|
77
89
|
const pluginPath = path.join(REGISTRY_PATH, framework.path);
|
|
78
90
|
const versionPath = path.join(pluginPath, version);
|
|
79
|
-
|
|
80
91
|
const { valid, missing } = validatePluginFiles(pluginPath, version);
|
|
81
|
-
|
|
82
92
|
if (!valid) {
|
|
83
93
|
throw new Error(
|
|
84
94
|
`Missing files for ${framework.name} ${version}: ` + missing.join(', ')
|
|
85
95
|
);
|
|
86
96
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
97
|
+
const meta = JSON.parse(
|
|
98
|
+
fs.readFileSync(path.join(pluginPath, 'plugin.json'), 'utf8')
|
|
99
|
+
);
|
|
100
|
+
const { default: questions } = await import(
|
|
101
|
+
path.join(versionPath, 'questions.js')
|
|
102
|
+
);
|
|
103
|
+
const { default: scaffold } = await import(
|
|
104
|
+
path.join(versionPath, 'scaffold.js')
|
|
105
|
+
);
|
|
106
|
+
return { meta, questions, scaffold };
|
|
93
107
|
};
|
|
94
108
|
|
|
95
|
-
const formatFrameworkLine = f =>
|
|
96
|
-
|
|
97
|
-
|
|
109
|
+
const formatFrameworkLine = f => {
|
|
110
|
+
const versionsStr = f.versions
|
|
111
|
+
.map(v => (v === f.latest ? chalk.green(`${v} (latest)`) : chalk.gray(v)))
|
|
112
|
+
.join(chalk.gray(', '));
|
|
113
|
+
return (
|
|
114
|
+
chalk.white(` • ${f.name}`) +
|
|
115
|
+
chalk.gray(` (${f.alias.join(', ')}) — `) +
|
|
116
|
+
versionsStr
|
|
117
|
+
);
|
|
118
|
+
};
|
|
98
119
|
|
|
99
120
|
const displayFrameworks = () => {
|
|
100
|
-
const frameworks =
|
|
101
|
-
|
|
121
|
+
const frameworks = getAvailableFrameworks();
|
|
102
122
|
if (frameworks.length === 0) {
|
|
103
123
|
console.log(chalk.red('\n❌ No frameworks found\n'));
|
|
104
124
|
return;
|
|
105
125
|
}
|
|
106
|
-
|
|
107
126
|
const grouped = groupByLanguage(frameworks);
|
|
108
|
-
|
|
109
127
|
console.log(chalk.bold('\n📦 Available Frameworks:\n'));
|
|
110
|
-
|
|
111
128
|
Object.entries(grouped).forEach(([lang, list]) => {
|
|
112
129
|
console.log(chalk.cyan(` ${lang.toUpperCase()}`));
|
|
113
130
|
list.forEach(f => console.log(formatFrameworkLine(f)));
|
|
@@ -115,9 +132,11 @@ const displayFrameworks = () => {
|
|
|
115
132
|
});
|
|
116
133
|
};
|
|
117
134
|
|
|
118
|
-
|
|
135
|
+
export {
|
|
119
136
|
loadIndex,
|
|
120
137
|
getFrameworks,
|
|
138
|
+
getAvailableFrameworks,
|
|
139
|
+
isPluginComplete,
|
|
121
140
|
findFramework,
|
|
122
141
|
searchFrameworks,
|
|
123
142
|
groupByLanguage,
|
package/core/utils.js
CHANGED
|
@@ -1,40 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
import chalk from 'chalk';
|
|
2
2
|
|
|
3
3
|
const log = message => {
|
|
4
4
|
console.log(chalk.white(` ${message}`));
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
// ─── Success Message ───────────────────────────────────
|
|
8
7
|
const success = message => {
|
|
9
8
|
console.log(chalk.green(`\n ${message}\n`));
|
|
10
9
|
};
|
|
11
10
|
|
|
12
|
-
// ─── Warning Message ───────────────────────────────────
|
|
13
11
|
const warn = message => {
|
|
14
12
|
console.log(chalk.yellow(` ⚠️ ${message}`));
|
|
15
13
|
};
|
|
16
14
|
|
|
17
|
-
// ─── Error Message ─────────────────────────────────────
|
|
18
15
|
const error = message => {
|
|
19
16
|
console.log(chalk.red(` ❌ ${message}`));
|
|
20
17
|
};
|
|
21
18
|
|
|
22
|
-
// ─── Section Title ─────────────────────────────────────
|
|
23
19
|
const title = message => {
|
|
24
20
|
console.log(chalk.cyan.bold(`\n ── ${message} ──\n`));
|
|
25
21
|
};
|
|
26
22
|
|
|
27
|
-
// ─── Divider Line ──────────────────────────────────────
|
|
28
23
|
const divider = () => {
|
|
29
24
|
console.log(chalk.gray(' ──────────────────────────────────────────'));
|
|
30
25
|
};
|
|
31
26
|
|
|
32
|
-
// ─── Step Indicator ────────────────────────────────────
|
|
33
27
|
const step = (number, message) => {
|
|
34
28
|
console.log(chalk.cyan(` [${number}]`) + chalk.white(` ${message}`));
|
|
35
29
|
};
|
|
36
30
|
|
|
37
|
-
// ─── Build Utils Object For Plugins ───────────────────
|
|
38
31
|
const buildPluginUtils = executor => ({
|
|
39
32
|
run: executor.run,
|
|
40
33
|
runInProject: executor.runInProject,
|
|
@@ -50,14 +43,4 @@ const buildPluginUtils = executor => ({
|
|
|
50
43
|
divider,
|
|
51
44
|
});
|
|
52
45
|
|
|
53
|
-
|
|
54
|
-
module.exports = {
|
|
55
|
-
log,
|
|
56
|
-
success,
|
|
57
|
-
warn,
|
|
58
|
-
error,
|
|
59
|
-
title,
|
|
60
|
-
divider,
|
|
61
|
-
step,
|
|
62
|
-
buildPluginUtils,
|
|
63
|
-
};
|
|
46
|
+
export { log, success, warn, error, title, divider, step, buildPluginUtils };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scaffy-tool",
|
|
3
|
-
"type": "
|
|
4
|
-
"version": "0.
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "1.0.1",
|
|
5
5
|
"description": "One command. Any framework. Ready to code.",
|
|
6
6
|
"author": "Md Tanvir Hossen <tanvirhossen112@gmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"scaffy": "cli.js"
|
|
11
11
|
},
|
|
12
12
|
"engines": {
|
|
13
|
-
"node": ">=
|
|
13
|
+
"node": ">=20.0.0"
|
|
14
14
|
},
|
|
15
15
|
"keywords": [
|
|
16
16
|
"scaffolding",
|
|
@@ -41,10 +41,10 @@
|
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|
|
43
43
|
"start": "node cli.js",
|
|
44
|
-
"test": "jest",
|
|
45
|
-
"test:
|
|
46
|
-
"test:
|
|
47
|
-
"test:ci": "jest --coverage --ci --runInBand",
|
|
44
|
+
"test": "node --experimental-vm-modules node_modules/.bin/jest",
|
|
45
|
+
"test:coverage": "node --experimental-vm-modules node_modules/.bin/jest --coverage",
|
|
46
|
+
"test:watch": "node --experimental-vm-modules node_modules/.bin/jest --watch",
|
|
47
|
+
"test:ci": "node --experimental-vm-modules node_modules/.bin/jest --coverage --ci --runInBand",
|
|
48
48
|
"lint": "eslint .",
|
|
49
49
|
"lint:fix": "eslint . --fix",
|
|
50
50
|
"format": "prettier --write .",
|
|
@@ -52,11 +52,11 @@
|
|
|
52
52
|
"prepare": "husky install"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"chalk": "^
|
|
55
|
+
"chalk": "^5.6.2",
|
|
56
56
|
"commander": "^11.1.0",
|
|
57
57
|
"figlet": "^1.10.0",
|
|
58
|
-
"inquirer": "^
|
|
59
|
-
"ora": "^
|
|
58
|
+
"inquirer": "^13.3.2",
|
|
59
|
+
"ora": "^9.3.0",
|
|
60
60
|
"semver": "^7.7.4"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"!(jest.config).js": [
|
|
74
74
|
"eslint --fix",
|
|
75
75
|
"prettier --write",
|
|
76
|
-
"jest --bail --findRelatedTests"
|
|
76
|
+
"node --experimental-vm-modules node_modules/.bin/jest --bail --findRelatedTests"
|
|
77
77
|
],
|
|
78
78
|
"*.json": [
|
|
79
79
|
"prettier --write"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Gin",
|
|
3
|
+
"alias": ["gin"],
|
|
4
|
+
"language": "go",
|
|
5
|
+
"latest": "v1",
|
|
6
|
+
"versions": ["v1"],
|
|
7
|
+
"description": "Fast and lightweight Go web framework",
|
|
8
|
+
"requires": [
|
|
9
|
+
{
|
|
10
|
+
"tool": "go",
|
|
11
|
+
"checkCommand": "go version",
|
|
12
|
+
"parseVersion": "go version go([0-9]+\\.[0-9]+\\.[0-9]+)",
|
|
13
|
+
"minVersion": "1.21.0",
|
|
14
|
+
"installGuide": {
|
|
15
|
+
"mac": "brew install go",
|
|
16
|
+
"linux": "sudo apt install golang-go",
|
|
17
|
+
"windows": "https://go.dev/dl",
|
|
18
|
+
"docs": "https://go.dev"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"maintainer": "community"
|
|
23
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export default [
|
|
2
|
+
{
|
|
3
|
+
type: 'select',
|
|
4
|
+
name: 'database',
|
|
5
|
+
message: 'Database?',
|
|
6
|
+
choices: [
|
|
7
|
+
{ name: 'None', value: 'none' },
|
|
8
|
+
{ name: 'PostgreSQL — GORM + postgres driver', value: 'postgresql' },
|
|
9
|
+
{ name: 'MySQL — GORM + mysql driver', value: 'mysql' },
|
|
10
|
+
{ name: 'SQLite — GORM + sqlite driver', value: 'sqlite' },
|
|
11
|
+
],
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
type: 'confirm',
|
|
15
|
+
name: 'docker',
|
|
16
|
+
message: 'Include Docker config?',
|
|
17
|
+
default: false,
|
|
18
|
+
},
|
|
19
|
+
];
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
export default async (answers, utils) => {
|
|
2
|
+
const { projectName, database, docker } = answers;
|
|
3
|
+
|
|
4
|
+
utils.title('Creating Gin v1 Project');
|
|
5
|
+
|
|
6
|
+
// ─── Step 1: Create project folder ────────────────────
|
|
7
|
+
utils.step(1, 'Creating project structure');
|
|
8
|
+
await utils.run(`mkdir ${projectName}`);
|
|
9
|
+
|
|
10
|
+
// ─── Step 2: Initialize Go module ─────────────────────
|
|
11
|
+
utils.step(2, 'Initializing Go module');
|
|
12
|
+
await utils.runInProject(projectName, `go mod init ${projectName}`);
|
|
13
|
+
|
|
14
|
+
// ─── Step 3: Install Gin ───────────────────────────────
|
|
15
|
+
utils.step(3, 'Installing Gin');
|
|
16
|
+
await utils.runInProject(projectName, 'go get github.com/gin-gonic/gin');
|
|
17
|
+
|
|
18
|
+
// ─── Step 4: Database ─────────────────────────────────
|
|
19
|
+
if (database !== 'none') {
|
|
20
|
+
utils.step(4, 'Installing database dependencies');
|
|
21
|
+
await utils.runInProject(projectName, 'go get gorm.io/gorm');
|
|
22
|
+
|
|
23
|
+
if (database === 'postgresql') {
|
|
24
|
+
await utils.runInProject(projectName, 'go get gorm.io/driver/postgres');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (database === 'mysql') {
|
|
28
|
+
await utils.runInProject(projectName, 'go get gorm.io/driver/mysql');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (database === 'sqlite') {
|
|
32
|
+
await utils.runInProject(projectName, 'go get gorm.io/driver/sqlite');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ─── Step 5: Generate main.go ─────────────────────────
|
|
37
|
+
utils.step(5, 'Generating application files');
|
|
38
|
+
|
|
39
|
+
const mainGo = `package main
|
|
40
|
+
|
|
41
|
+
import (
|
|
42
|
+
"net/http"
|
|
43
|
+
|
|
44
|
+
"github.com/gin-gonic/gin"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
func main() {
|
|
48
|
+
r := gin.Default()
|
|
49
|
+
|
|
50
|
+
r.GET("/", func(c *gin.Context) {
|
|
51
|
+
c.JSON(http.StatusOK, gin.H{
|
|
52
|
+
"message": "Hello from ${projectName}",
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
r.GET("/health", func(c *gin.Context) {
|
|
57
|
+
c.JSON(http.StatusOK, gin.H{
|
|
58
|
+
"status": "ok",
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
r.Run(":8080")
|
|
63
|
+
}
|
|
64
|
+
`;
|
|
65
|
+
|
|
66
|
+
await utils.createFile(`${projectName}/main.go`, mainGo);
|
|
67
|
+
|
|
68
|
+
// ─── Step 6: Generate database.go if needed ───────────
|
|
69
|
+
if (database !== 'none') {
|
|
70
|
+
const dsnMap = {
|
|
71
|
+
postgresql: `host=localhost user=postgres password=password dbname=${projectName} port=5432 sslmode=disable`,
|
|
72
|
+
mysql: `user:password@tcp(localhost:3306)/${projectName}?charset=utf8mb4&parseTime=True&loc=Local`,
|
|
73
|
+
sqlite: `${projectName}.db`,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const driverMap = {
|
|
77
|
+
postgresql: 'postgres',
|
|
78
|
+
mysql: 'mysql',
|
|
79
|
+
sqlite: 'sqlite',
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const databaseGo = `package main
|
|
83
|
+
|
|
84
|
+
import (
|
|
85
|
+
"log"
|
|
86
|
+
|
|
87
|
+
"gorm.io/driver/${driverMap[database]}"
|
|
88
|
+
"gorm.io/gorm"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
var DB *gorm.DB
|
|
92
|
+
|
|
93
|
+
func initDB() {
|
|
94
|
+
dsn := "${dsnMap[database]}"
|
|
95
|
+
db, err := gorm.Open(${driverMap[database]}.Open(dsn), &gorm.Config{})
|
|
96
|
+
if err != nil {
|
|
97
|
+
log.Fatal("Failed to connect to database:", err)
|
|
98
|
+
}
|
|
99
|
+
DB = db
|
|
100
|
+
}
|
|
101
|
+
`;
|
|
102
|
+
await utils.createFile(`${projectName}/database.go`, databaseGo);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ─── Step 7: Generate .gitignore ──────────────────────
|
|
106
|
+
const gitignore = `# Binaries
|
|
107
|
+
${projectName}
|
|
108
|
+
*.exe
|
|
109
|
+
*.exe~
|
|
110
|
+
*.dll
|
|
111
|
+
*.so
|
|
112
|
+
*.dylib
|
|
113
|
+
|
|
114
|
+
# Test binary
|
|
115
|
+
*.test
|
|
116
|
+
|
|
117
|
+
# Output of go coverage tool
|
|
118
|
+
*.out
|
|
119
|
+
|
|
120
|
+
# Environment
|
|
121
|
+
.env
|
|
122
|
+
|
|
123
|
+
# IDE
|
|
124
|
+
.vscode/
|
|
125
|
+
.idea/
|
|
126
|
+
`;
|
|
127
|
+
await utils.createFile(`${projectName}/.gitignore`, gitignore);
|
|
128
|
+
|
|
129
|
+
// ─── Step 8: Docker ───────────────────────────────────
|
|
130
|
+
if (docker) {
|
|
131
|
+
utils.step(6, 'Creating Docker config');
|
|
132
|
+
|
|
133
|
+
const dockerfile = `FROM golang:1.21-alpine AS builder
|
|
134
|
+
|
|
135
|
+
WORKDIR /app
|
|
136
|
+
|
|
137
|
+
COPY go.mod go.sum ./
|
|
138
|
+
RUN go mod download
|
|
139
|
+
|
|
140
|
+
COPY . .
|
|
141
|
+
RUN go build -o main .
|
|
142
|
+
|
|
143
|
+
FROM alpine:latest
|
|
144
|
+
|
|
145
|
+
WORKDIR /app
|
|
146
|
+
COPY --from=builder /app/main .
|
|
147
|
+
|
|
148
|
+
EXPOSE 8080
|
|
149
|
+
CMD ["./main"]
|
|
150
|
+
`;
|
|
151
|
+
|
|
152
|
+
const dockerCompose = `version: '3.8'
|
|
153
|
+
services:
|
|
154
|
+
web:
|
|
155
|
+
build: .
|
|
156
|
+
ports:
|
|
157
|
+
- "8080:8080"
|
|
158
|
+
depends_on:
|
|
159
|
+
- db
|
|
160
|
+
${
|
|
161
|
+
database === 'postgresql'
|
|
162
|
+
? ` db:
|
|
163
|
+
image: postgres:15
|
|
164
|
+
environment:
|
|
165
|
+
POSTGRES_PASSWORD: password
|
|
166
|
+
POSTGRES_DB: ${projectName}
|
|
167
|
+
ports:
|
|
168
|
+
- "5432:5432"`
|
|
169
|
+
: ''
|
|
170
|
+
}
|
|
171
|
+
${
|
|
172
|
+
database === 'mysql'
|
|
173
|
+
? ` db:
|
|
174
|
+
image: mysql:8.0
|
|
175
|
+
environment:
|
|
176
|
+
MYSQL_ROOT_PASSWORD: password
|
|
177
|
+
MYSQL_DATABASE: ${projectName}
|
|
178
|
+
ports:
|
|
179
|
+
- "3306:3306"`
|
|
180
|
+
: ''
|
|
181
|
+
}
|
|
182
|
+
`;
|
|
183
|
+
|
|
184
|
+
await utils.createFile(`${projectName}/Dockerfile`, dockerfile);
|
|
185
|
+
await utils.createFile(`${projectName}/docker-compose.yml`, dockerCompose);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ─── Step 9: go mod tidy ──────────────────────────────
|
|
189
|
+
utils.step(7, 'Tidying Go modules');
|
|
190
|
+
await utils.runInProject(projectName, 'go mod tidy');
|
|
191
|
+
|
|
192
|
+
utils.success(`Gin v1 project "${projectName}" created successfully!`);
|
|
193
|
+
utils.log(` cd ${projectName}`);
|
|
194
|
+
utils.log(` go run main.go`);
|
|
195
|
+
utils.log(` Server running at http://localhost:8080`);
|
|
196
|
+
};
|
package/registry/index.json
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
"name": "Laravel",
|
|
6
6
|
"alias": ["laravel"],
|
|
7
7
|
"language": "php",
|
|
8
|
-
"latest": "
|
|
9
|
-
"versions": ["
|
|
8
|
+
"latest": "v13",
|
|
9
|
+
"versions": ["v13", "v12", "v11"],
|
|
10
10
|
"path": "php/laravel"
|
|
11
11
|
},
|
|
12
12
|
{
|
|
@@ -61,8 +61,8 @@
|
|
|
61
61
|
"name": "FastAPI",
|
|
62
62
|
"alias": ["fastapi"],
|
|
63
63
|
"language": "python",
|
|
64
|
-
"latest": "
|
|
65
|
-
"versions": ["
|
|
64
|
+
"latest": "v1",
|
|
65
|
+
"versions": ["v1"],
|
|
66
66
|
"path": "python/fastapi"
|
|
67
67
|
},
|
|
68
68
|
{
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ExpressJS",
|
|
3
|
+
"alias": ["express", "expressjs"],
|
|
4
|
+
"language": "javascript",
|
|
5
|
+
"latest": "v4",
|
|
6
|
+
"versions": ["v4"],
|
|
7
|
+
"description": "Fast, minimalist web framework for Node.js",
|
|
8
|
+
"requires": [
|
|
9
|
+
{
|
|
10
|
+
"tool": "node",
|
|
11
|
+
"checkCommand": "node --version",
|
|
12
|
+
"parseVersion": "v([0-9]+\\.[0-9]+\\.[0-9]+)",
|
|
13
|
+
"minVersion": "18.0.0",
|
|
14
|
+
"installGuide": {
|
|
15
|
+
"mac": "brew install node",
|
|
16
|
+
"linux": "sudo apt install nodejs",
|
|
17
|
+
"windows": "https://nodejs.org",
|
|
18
|
+
"docs": "https://nodejs.org"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"tool": "npm",
|
|
23
|
+
"checkCommand": "npm --version",
|
|
24
|
+
"parseVersion": "([0-9]+\\.[0-9]+\\.[0-9]+)",
|
|
25
|
+
"minVersion": "8.0.0",
|
|
26
|
+
"installGuide": {
|
|
27
|
+
"mac": "brew install node",
|
|
28
|
+
"linux": "sudo apt install npm",
|
|
29
|
+
"windows": "https://nodejs.org",
|
|
30
|
+
"docs": "https://docs.npmjs.com"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"packageManagerQuestion": {
|
|
35
|
+
"tool": "packageManager",
|
|
36
|
+
"message": "Package manager:",
|
|
37
|
+
"choices": [
|
|
38
|
+
{ "name": "npm", "value": "npm", "checkCommand": "npm --version" },
|
|
39
|
+
{ "name": "yarn", "value": "yarn", "checkCommand": "yarn --version" },
|
|
40
|
+
{ "name": "pnpm", "value": "pnpm", "checkCommand": "pnpm --version" }
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"maintainer": "community"
|
|
44
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { detectAvailableChoices } from '../../../../core/detector.js';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
|
|
4
|
+
const require = createRequire(import.meta.url);
|
|
5
|
+
const pluginMeta = require('../plugin.json');
|
|
6
|
+
|
|
7
|
+
export default async () => {
|
|
8
|
+
const availableManagers = await detectAvailableChoices(
|
|
9
|
+
pluginMeta.packageManagerQuestion.choices
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
return [
|
|
13
|
+
{
|
|
14
|
+
type: 'select',
|
|
15
|
+
name: 'packageManager',
|
|
16
|
+
message: pluginMeta.packageManagerQuestion.message,
|
|
17
|
+
choices: availableManagers,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
type: 'confirm',
|
|
21
|
+
name: 'typescript',
|
|
22
|
+
message: 'Use TypeScript?',
|
|
23
|
+
default: false,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type: 'select',
|
|
27
|
+
name: 'database',
|
|
28
|
+
message: 'Database?',
|
|
29
|
+
choices: [
|
|
30
|
+
{ name: 'None', value: 'none' },
|
|
31
|
+
{ name: 'MongoDB — Mongoose ODM', value: 'mongodb' },
|
|
32
|
+
{ name: 'PostgreSQL — pg driver', value: 'postgresql' },
|
|
33
|
+
{ name: 'MySQL — mysql2 driver', value: 'mysql' },
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
type: 'confirm',
|
|
38
|
+
name: 'docker',
|
|
39
|
+
message: 'Include Docker config?',
|
|
40
|
+
default: false,
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
};
|