@dawitworku/projectcli 0.1.3 → 0.2.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/package.json +1 -1
- package/src/cicd.js +169 -0
- package/src/descriptions.js +45 -0
- package/src/index.js +126 -0
- package/src/libraries.js +49 -0
- package/src/pm.js +28 -1
- package/src/registry.js +12 -22
package/package.json
CHANGED
package/src/cicd.js
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
const fs = require("node:fs");
|
|
2
|
+
const path = require("node:path");
|
|
3
|
+
|
|
4
|
+
const GITHUB_ACTIONS_JS = `name: CI
|
|
5
|
+
on: [push, pull_request]
|
|
6
|
+
jobs:
|
|
7
|
+
build:
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
steps:
|
|
10
|
+
- uses: actions/checkout@v4
|
|
11
|
+
- uses: actions/setup-node@v4
|
|
12
|
+
with:
|
|
13
|
+
node-version: 20
|
|
14
|
+
cache: 'npm'
|
|
15
|
+
- run: npm ci
|
|
16
|
+
- run: npm run build --if-present
|
|
17
|
+
- run: npm test --if-present
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
const GITHUB_ACTIONS_PY = `name: CI
|
|
21
|
+
on: [push, pull_request]
|
|
22
|
+
jobs:
|
|
23
|
+
build:
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v4
|
|
27
|
+
- uses: actions/setup-python@v5
|
|
28
|
+
with:
|
|
29
|
+
python-version: '3.11'
|
|
30
|
+
cache: 'pip'
|
|
31
|
+
- run: pip install -r requirements.txt
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
const GITHUB_ACTIONS_RUST = `name: CI
|
|
35
|
+
on: [push, pull_request]
|
|
36
|
+
jobs:
|
|
37
|
+
build:
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
steps:
|
|
40
|
+
- uses: actions/checkout@v4
|
|
41
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
42
|
+
- run: cargo build --verbose
|
|
43
|
+
- run: cargo test --verbose
|
|
44
|
+
`;
|
|
45
|
+
|
|
46
|
+
const GITHUB_ACTIONS_GO = `name: CI
|
|
47
|
+
on: [push, pull_request]
|
|
48
|
+
jobs:
|
|
49
|
+
build:
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
steps:
|
|
52
|
+
- uses: actions/checkout@v4
|
|
53
|
+
- uses: actions/setup-go@v5
|
|
54
|
+
with:
|
|
55
|
+
go-version: '1.21'
|
|
56
|
+
- run: go build -v ./...
|
|
57
|
+
- run: go test -v ./...
|
|
58
|
+
`;
|
|
59
|
+
|
|
60
|
+
function getGitHubAction(language, pm) {
|
|
61
|
+
if (language === "JavaScript" || language === "TypeScript")
|
|
62
|
+
return GITHUB_ACTIONS_JS;
|
|
63
|
+
if (language === "Python") return GITHUB_ACTIONS_PY;
|
|
64
|
+
if (language === "Rust") return GITHUB_ACTIONS_RUST;
|
|
65
|
+
if (language === "Go") return GITHUB_ACTIONS_GO;
|
|
66
|
+
// Default generic
|
|
67
|
+
return `name: CI
|
|
68
|
+
on: [push, pull_request]
|
|
69
|
+
jobs:
|
|
70
|
+
build:
|
|
71
|
+
runs-on: ubuntu-latest
|
|
72
|
+
steps:
|
|
73
|
+
- uses: actions/checkout@v4
|
|
74
|
+
- run: echo "Add build steps here"
|
|
75
|
+
`;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const DOCKERFILE_JS = `FROM node:20-alpine AS base
|
|
79
|
+
|
|
80
|
+
FROM base AS deps
|
|
81
|
+
WORKDIR /app
|
|
82
|
+
COPY package.json ./
|
|
83
|
+
RUN npm install
|
|
84
|
+
|
|
85
|
+
FROM base AS runner
|
|
86
|
+
WORKDIR /app
|
|
87
|
+
COPY --from=deps /app/node_modules ./node_modules
|
|
88
|
+
COPY . .
|
|
89
|
+
# RUN npm run build
|
|
90
|
+
CMD ["node", "index.js"]
|
|
91
|
+
`;
|
|
92
|
+
|
|
93
|
+
const DOCKERFILE_PY = `FROM python:3.11-slim
|
|
94
|
+
WORKDIR /app
|
|
95
|
+
COPY requirements.txt .
|
|
96
|
+
RUN pip install -r requirements.txt
|
|
97
|
+
COPY . .
|
|
98
|
+
CMD ["python", "app.py"]
|
|
99
|
+
`;
|
|
100
|
+
|
|
101
|
+
const DOCKERFILE_GO = `FROM golang:1.21-alpine AS builder
|
|
102
|
+
WORKDIR /app
|
|
103
|
+
COPY . .
|
|
104
|
+
RUN go build -o myapp main.go
|
|
105
|
+
|
|
106
|
+
FROM alpine:latest
|
|
107
|
+
WORKDIR /app
|
|
108
|
+
COPY --from=builder /app/myapp .
|
|
109
|
+
CMD ["./myapp"]
|
|
110
|
+
`;
|
|
111
|
+
|
|
112
|
+
const DOCKERFILE_RUST = `FROM rust:1.75 as builder
|
|
113
|
+
WORKDIR /usr/src/myapp
|
|
114
|
+
COPY . .
|
|
115
|
+
RUN cargo install --path .
|
|
116
|
+
|
|
117
|
+
FROM debian:buster-slim
|
|
118
|
+
COPY --from=builder /usr/local/cargo/bin/myapp /usr/local/bin/myapp
|
|
119
|
+
CMD ["myapp"]
|
|
120
|
+
`;
|
|
121
|
+
|
|
122
|
+
function getDockerfile(language) {
|
|
123
|
+
if (language === "JavaScript" || language === "TypeScript")
|
|
124
|
+
return DOCKERFILE_JS;
|
|
125
|
+
if (language === "Python") return DOCKERFILE_PY;
|
|
126
|
+
if (language === "Go") return DOCKERFILE_GO;
|
|
127
|
+
if (language === "Rust") return DOCKERFILE_RUST;
|
|
128
|
+
return `# Dockerfile
|
|
129
|
+
FROM ubuntu:latest
|
|
130
|
+
WORKDIR /app
|
|
131
|
+
COPY . .
|
|
132
|
+
CMD ["echo", "Start..."]
|
|
133
|
+
`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function generateCI(projectRoot, language, pm) {
|
|
137
|
+
const steps = [];
|
|
138
|
+
|
|
139
|
+
// GitHub Actions
|
|
140
|
+
const ghContent = getGitHubAction(language, pm);
|
|
141
|
+
steps.push({
|
|
142
|
+
type: "writeFile",
|
|
143
|
+
path: ".github/workflows/ci.yml",
|
|
144
|
+
content: ghContent,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
return steps;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function generateDocker(projectRoot, language) {
|
|
151
|
+
const content = getDockerfile(language);
|
|
152
|
+
return [
|
|
153
|
+
{
|
|
154
|
+
type: "writeFile",
|
|
155
|
+
path: "Dockerfile",
|
|
156
|
+
content: content,
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
type: "writeFile",
|
|
160
|
+
path: ".dockerignore",
|
|
161
|
+
content: "node_modules\ntarget\n.venv\n.git\n",
|
|
162
|
+
},
|
|
163
|
+
];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
module.exports = {
|
|
167
|
+
generateCI,
|
|
168
|
+
generateDocker,
|
|
169
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const DESCRIPTIONS = {
|
|
2
|
+
// JavaScript
|
|
3
|
+
"js.vite.vanilla":
|
|
4
|
+
"Native ESM-based build tool. Best for: fast prototyping, zero-framework learning.",
|
|
5
|
+
"js.vite.react":
|
|
6
|
+
"Most popular UI library. Best for: interactive UIs, large ecosystem, jobs.",
|
|
7
|
+
"js.vite.vue":
|
|
8
|
+
"Progressive framework. Best for: easy learning curve, clean template syntax.",
|
|
9
|
+
"js.vite.svelte":
|
|
10
|
+
"Compiler-based framework. Best for: performance, less boilerplate, true reactivity.",
|
|
11
|
+
"js.nextjs":
|
|
12
|
+
"The React Framework for the Web. Best for: SEO, SSR/SSG, full-stack apps.",
|
|
13
|
+
"js.astro":
|
|
14
|
+
"Content-focused site builder. Best for: blogs, documentation, portfolios (ships less JS).",
|
|
15
|
+
"js.express":
|
|
16
|
+
"Minimalist web framework for Node.js. Best for: REST APIs, learning backend basics.",
|
|
17
|
+
"js.nestjs":
|
|
18
|
+
"Angular-style backend framework. Best for: enterprise, scalable architecture, TypeScript.",
|
|
19
|
+
|
|
20
|
+
// Python
|
|
21
|
+
"py.django":
|
|
22
|
+
"Batteries-included web framework. Best for: rapid dev, CMS, huge ecosystem.",
|
|
23
|
+
"py.flask.basic":
|
|
24
|
+
"Microframework. Best for: simple services, learning, flexibility.",
|
|
25
|
+
"py.fastapi.basic":
|
|
26
|
+
"Modern, fast (high-performance). Best for: APIs with auto-docs (Swagger), async support.",
|
|
27
|
+
|
|
28
|
+
// Rust
|
|
29
|
+
"rs.cargo.bin":
|
|
30
|
+
"Standard Rust binary. Best for: CLI tools, backend services, learning Rust.",
|
|
31
|
+
"rs.tauri":
|
|
32
|
+
"Build smaller, faster, and more secure desktop applications with a web frontend.",
|
|
33
|
+
|
|
34
|
+
// Go
|
|
35
|
+
"go.module.basic":
|
|
36
|
+
"Go's dependency management system. Best for: microservices, high concurrency.",
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
function getDescription(id) {
|
|
40
|
+
return DESCRIPTIONS[id] || "No description available.";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
module.exports = {
|
|
44
|
+
getDescription,
|
|
45
|
+
};
|
package/src/index.js
CHANGED
|
@@ -28,6 +28,8 @@ try {
|
|
|
28
28
|
const { getLanguages, getFrameworks, getGenerator } = require("./registry");
|
|
29
29
|
const { runSteps } = require("./run");
|
|
30
30
|
const { runAdd } = require("./add");
|
|
31
|
+
const { generateCI, generateDocker } = require("./cicd");
|
|
32
|
+
const { getDescription } = require("./descriptions");
|
|
31
33
|
|
|
32
34
|
const RUST_KEYWORDS = new Set(
|
|
33
35
|
[
|
|
@@ -129,6 +131,9 @@ function parseArgs(argv) {
|
|
|
129
131
|
framework: undefined,
|
|
130
132
|
name: undefined,
|
|
131
133
|
pm: undefined,
|
|
134
|
+
ci: false,
|
|
135
|
+
docker: false,
|
|
136
|
+
learning: false,
|
|
132
137
|
};
|
|
133
138
|
|
|
134
139
|
const nextValue = (i) => {
|
|
@@ -143,6 +148,9 @@ function parseArgs(argv) {
|
|
|
143
148
|
else if (a === "--list") out.list = true;
|
|
144
149
|
else if (a === "--yes" || a === "-y") out.yes = true;
|
|
145
150
|
else if (a === "--dry-run") out.dryRun = true;
|
|
151
|
+
else if (a === "--ci") out.ci = true;
|
|
152
|
+
else if (a === "--docker") out.docker = true;
|
|
153
|
+
else if (a === "--learning") out.learning = true;
|
|
146
154
|
else if (a.startsWith("--language="))
|
|
147
155
|
out.language = a.slice("--language=".length);
|
|
148
156
|
else if (a === "--language") {
|
|
@@ -202,6 +210,9 @@ function printHelp() {
|
|
|
202
210
|
console.log(
|
|
203
211
|
" --pm Package manager for JS/TS (npm|pnpm|yarn|bun)"
|
|
204
212
|
);
|
|
213
|
+
console.log(" --ci Auto-add GitHub Actions CI");
|
|
214
|
+
console.log(" --docker Auto-add Dockerfile");
|
|
215
|
+
console.log(" --learning Enable learning mode (shows descriptions)");
|
|
205
216
|
}
|
|
206
217
|
|
|
207
218
|
const BACK = "__back__";
|
|
@@ -247,6 +258,18 @@ function printList() {
|
|
|
247
258
|
}
|
|
248
259
|
}
|
|
249
260
|
|
|
261
|
+
function showBanner() {
|
|
262
|
+
console.log("");
|
|
263
|
+
console.log(
|
|
264
|
+
gradient.pastel.multiline(
|
|
265
|
+
figlet.textSync("ProjectCLI", { font: "Standard" })
|
|
266
|
+
)
|
|
267
|
+
);
|
|
268
|
+
console.log(chalk.bold.magenta(" The Swiss Army Knife for Developers"));
|
|
269
|
+
console.log(chalk.dim(" v" + readPackageVersion()));
|
|
270
|
+
console.log("");
|
|
271
|
+
}
|
|
272
|
+
|
|
250
273
|
async function main(options = {}) {
|
|
251
274
|
if (!prompt) {
|
|
252
275
|
throw new Error(
|
|
@@ -257,7 +280,19 @@ async function main(options = {}) {
|
|
|
257
280
|
const argv = options.argv || [];
|
|
258
281
|
const { cmd, rest } = splitCommand(argv);
|
|
259
282
|
const args = parseArgs(rest);
|
|
283
|
+
|
|
284
|
+
if (
|
|
285
|
+
!args.list &&
|
|
286
|
+
!args.version &&
|
|
287
|
+
!args.help &&
|
|
288
|
+
rest.length === 0 &&
|
|
289
|
+
cmd === "init"
|
|
290
|
+
) {
|
|
291
|
+
showBanner();
|
|
292
|
+
}
|
|
293
|
+
|
|
260
294
|
if (args.help) {
|
|
295
|
+
showBanner();
|
|
261
296
|
printHelp();
|
|
262
297
|
return;
|
|
263
298
|
}
|
|
@@ -526,6 +561,20 @@ async function main(options = {}) {
|
|
|
526
561
|
`Framework: ${state.framework}`,
|
|
527
562
|
];
|
|
528
563
|
if (state.pm) summaryLines.push(`Package manager: ${state.pm}`);
|
|
564
|
+
|
|
565
|
+
if (args.learning) {
|
|
566
|
+
const desc = getDescription(generator.id);
|
|
567
|
+
console.log(
|
|
568
|
+
chalk.cyan(
|
|
569
|
+
boxen(desc, {
|
|
570
|
+
padding: 1,
|
|
571
|
+
title: `About ${state.framework}`,
|
|
572
|
+
borderStyle: "round",
|
|
573
|
+
})
|
|
574
|
+
)
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
|
|
529
578
|
console.log("\n" + summaryLines.join("\n") + "\n");
|
|
530
579
|
|
|
531
580
|
if (targetExists && args.dryRun) {
|
|
@@ -623,6 +672,83 @@ async function main(options = {}) {
|
|
|
623
672
|
continue;
|
|
624
673
|
}
|
|
625
674
|
|
|
675
|
+
// Git init
|
|
676
|
+
if (!args.dryRun) {
|
|
677
|
+
let doGit = args.yes;
|
|
678
|
+
if (!doGit) {
|
|
679
|
+
const { git } = await prompt([
|
|
680
|
+
{
|
|
681
|
+
type: "confirm",
|
|
682
|
+
name: "git",
|
|
683
|
+
message: "Initialize a new git repository?",
|
|
684
|
+
default: true,
|
|
685
|
+
},
|
|
686
|
+
]);
|
|
687
|
+
doGit = git;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
if (doGit) {
|
|
691
|
+
try {
|
|
692
|
+
await runSteps(
|
|
693
|
+
[
|
|
694
|
+
{ program: "git", args: ["init"], cwdFromProjectRoot: true },
|
|
695
|
+
{
|
|
696
|
+
program: "git",
|
|
697
|
+
args: ["add", "."],
|
|
698
|
+
cwdFromProjectRoot: true,
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
program: "git",
|
|
702
|
+
args: ["commit", "-m", "Initial commit"],
|
|
703
|
+
cwdFromProjectRoot: true,
|
|
704
|
+
},
|
|
705
|
+
],
|
|
706
|
+
{ projectRoot }
|
|
707
|
+
);
|
|
708
|
+
console.log("Initialized git repository.");
|
|
709
|
+
} catch (e) {
|
|
710
|
+
console.warn("Git init failed (is git installed?):", e.message);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// CI/CD & Docker
|
|
716
|
+
if (!args.dryRun) {
|
|
717
|
+
let wantCi = args.ci;
|
|
718
|
+
let wantDocker = args.docker;
|
|
719
|
+
|
|
720
|
+
if (!args.yes) {
|
|
721
|
+
const { extras } = await prompt([
|
|
722
|
+
{
|
|
723
|
+
type: "checkbox",
|
|
724
|
+
name: "extras",
|
|
725
|
+
message: "Extras:",
|
|
726
|
+
choices: [
|
|
727
|
+
{ name: "GitHub Actions CI", value: "ci", checked: wantCi },
|
|
728
|
+
{ name: "Dockerfile", value: "docker", checked: wantDocker },
|
|
729
|
+
],
|
|
730
|
+
},
|
|
731
|
+
]);
|
|
732
|
+
if (extras) {
|
|
733
|
+
wantCi = extras.includes("ci");
|
|
734
|
+
wantDocker = extras.includes("docker");
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
const extraSteps = [];
|
|
739
|
+
if (wantCi) {
|
|
740
|
+
extraSteps.push(...generateCI(projectRoot, state.language, state.pm));
|
|
741
|
+
}
|
|
742
|
+
if (wantDocker) {
|
|
743
|
+
extraSteps.push(...generateDocker(projectRoot, state.language));
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
if (extraSteps.length > 0) {
|
|
747
|
+
console.log("Adding extras...");
|
|
748
|
+
await runSteps(extraSteps, { projectRoot });
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
|
|
626
752
|
console.log(`\nDone. Created project in: ${projectRoot}`);
|
|
627
753
|
return;
|
|
628
754
|
}
|
package/src/libraries.js
CHANGED
|
@@ -137,11 +137,60 @@ const GO = {
|
|
|
137
137
|
],
|
|
138
138
|
};
|
|
139
139
|
|
|
140
|
+
const PHP = {
|
|
141
|
+
"Web Frameworks": [
|
|
142
|
+
{ label: "Laravel", packages: ["laravel/framework"] },
|
|
143
|
+
{ label: "Symfony", packages: ["symfony/symfony"] },
|
|
144
|
+
{ label: "Slim", packages: ["slim/slim"] },
|
|
145
|
+
],
|
|
146
|
+
Testing: [
|
|
147
|
+
{ label: "PHPUnit", packages: [], packagesDev: ["phpunit/phpunit"] },
|
|
148
|
+
{ label: "Pest", packages: [], packagesDev: ["pestphp/pest"] },
|
|
149
|
+
],
|
|
150
|
+
Tools: [
|
|
151
|
+
{
|
|
152
|
+
label: "PHPStudio (CS Fixer)",
|
|
153
|
+
packages: [],
|
|
154
|
+
packagesDev: ["friendsofphp/php-cs-fixer"],
|
|
155
|
+
},
|
|
156
|
+
{ label: "Monolog", packages: ["monolog/monolog"] },
|
|
157
|
+
],
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const RUBY = {
|
|
161
|
+
Web: [
|
|
162
|
+
{ label: "Rails", packages: ["rails"] },
|
|
163
|
+
{ label: "Sinatra", packages: ["sinatra"] },
|
|
164
|
+
],
|
|
165
|
+
Testing: [{ label: "RSpec", packages: ["rspec"] }],
|
|
166
|
+
Tools: [{ label: "Rubocop", packages: ["rubocop"] }],
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const DART = {
|
|
170
|
+
"Web/App": [{ label: "Shelf (Server)", packages: ["shelf", "shelf_router"] }],
|
|
171
|
+
State: [
|
|
172
|
+
{ label: "Provider", packages: ["provider"] },
|
|
173
|
+
{ label: "Riverpod", packages: ["flutter_riverpod"] },
|
|
174
|
+
{ label: "Bloc", packages: ["flutter_bloc"] },
|
|
175
|
+
],
|
|
176
|
+
Utils: [
|
|
177
|
+
{ label: "Dio (HTTP)", packages: ["dio"] },
|
|
178
|
+
{
|
|
179
|
+
label: "Freezed",
|
|
180
|
+
packages: ["freezed_annotation"],
|
|
181
|
+
packagesDev: ["build_runner", "freezed"],
|
|
182
|
+
},
|
|
183
|
+
],
|
|
184
|
+
};
|
|
185
|
+
|
|
140
186
|
function getCatalog(language) {
|
|
141
187
|
if (language === "JavaScript/TypeScript") return JS_TS;
|
|
142
188
|
if (language === "Python") return PY;
|
|
143
189
|
if (language === "Rust") return RUST;
|
|
144
190
|
if (language === "Go") return GO;
|
|
191
|
+
if (language === "PHP") return PHP;
|
|
192
|
+
if (language === "Ruby") return RUBY;
|
|
193
|
+
if (language === "Dart") return DART;
|
|
145
194
|
return {};
|
|
146
195
|
}
|
|
147
196
|
|
package/src/pm.js
CHANGED
|
@@ -50,6 +50,33 @@ function pmAddCommand(pm, packages, { dev = false } = {}) {
|
|
|
50
50
|
return { program: "go", args: ["get", ...pkgs] };
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
// PHP
|
|
54
|
+
if (pm === "composer") {
|
|
55
|
+
return {
|
|
56
|
+
program: "composer",
|
|
57
|
+
args: ["require", ...(dev ? ["--dev"] : []), ...pkgs],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Ruby
|
|
62
|
+
if (pm === "bundle") {
|
|
63
|
+
// bundle add pkg
|
|
64
|
+
// dev dependencies often go to "development" or "test" group, but let's just do default add for now
|
|
65
|
+
// or standard "bundle add generic"
|
|
66
|
+
return {
|
|
67
|
+
program: "bundle",
|
|
68
|
+
args: ["add", ...pkgs, ...(dev ? ["--group", "development,test"] : [])],
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Dart
|
|
73
|
+
if (pm === "dart") {
|
|
74
|
+
return {
|
|
75
|
+
program: "dart",
|
|
76
|
+
args: ["pub", "add", ...(dev ? ["--dev"] : []), ...pkgs],
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
53
80
|
return { program: "npm", args: ["install", ...(dev ? ["-D"] : []), ...pkgs] };
|
|
54
81
|
}
|
|
55
82
|
|
|
@@ -58,7 +85,7 @@ function pmExecCommand(pm, pkg, pkgArgs) {
|
|
|
58
85
|
|
|
59
86
|
if (pm === "pnpm") return { program: "pnpm", args: ["dlx", pkg, ...args] };
|
|
60
87
|
if (pm === "yarn") return { program: "yarn", args: ["dlx", pkg, ...args] };
|
|
61
|
-
if (pm === "bun") return { program: "
|
|
88
|
+
if (pm === "bun") return { program: "bun", args: ["x", pkg, ...args] };
|
|
62
89
|
if (pm === "mvn")
|
|
63
90
|
return { program: "mvn", args: ["archetype:generate", ...args] };
|
|
64
91
|
if (pm === "gradle") return { program: "gradle", args: ["init", ...args] };
|
package/src/registry.js
CHANGED
|
@@ -429,17 +429,17 @@ const REGISTRY = {
|
|
|
429
429
|
type: "writeFile",
|
|
430
430
|
path: "app.py",
|
|
431
431
|
content:
|
|
432
|
-
"from flask import Flask
|
|
432
|
+
"from flask import Flask\\n\\napp = Flask(__name__)\\n\\n@app.get('/')\\ndef hello():\\n return {'status': 'ok'}\\n\\nif __name__ == '__main__':\\n app.run(debug=True)\\n",
|
|
433
433
|
},
|
|
434
434
|
{
|
|
435
435
|
type: "writeFile",
|
|
436
436
|
path: "requirements.txt",
|
|
437
|
-
content: "flask
|
|
437
|
+
content: "flask\\n",
|
|
438
438
|
},
|
|
439
439
|
{
|
|
440
440
|
type: "writeFile",
|
|
441
441
|
path: ".gitignore",
|
|
442
|
-
content: ".venv
|
|
442
|
+
content: ".venv\\n__pycache__\\n*.pyc\\n.DS_Store\\n",
|
|
443
443
|
},
|
|
444
444
|
],
|
|
445
445
|
notes: "Writes app.py + requirements.txt (no pip install).",
|
|
@@ -453,23 +453,23 @@ const REGISTRY = {
|
|
|
453
453
|
type: "writeFile",
|
|
454
454
|
path: "main.py",
|
|
455
455
|
content:
|
|
456
|
-
"from fastapi import FastAPI
|
|
456
|
+
"from fastapi import FastAPI\\n\\napp = FastAPI()\\n\\n@app.get('/')\\ndef root():\\n return {'status': 'ok'}\\n",
|
|
457
457
|
},
|
|
458
458
|
{
|
|
459
459
|
type: "writeFile",
|
|
460
460
|
path: "requirements.txt",
|
|
461
|
-
content: "fastapi
|
|
461
|
+
content: "fastapi\\nuvicorn\\n",
|
|
462
462
|
},
|
|
463
463
|
{
|
|
464
464
|
type: "writeFile",
|
|
465
465
|
path: "README.md",
|
|
466
466
|
content:
|
|
467
|
-
"# FastAPI app
|
|
467
|
+
"# FastAPI app\\n\\nRun:\\n\\n- python -m venv .venv\\n- . .venv/bin/activate\\n- pip install -r requirements.txt\\n- uvicorn main:app --reload\\n",
|
|
468
468
|
},
|
|
469
469
|
{
|
|
470
470
|
type: "writeFile",
|
|
471
471
|
path: ".gitignore",
|
|
472
|
-
content: ".venv
|
|
472
|
+
content: ".venv\\n__pycache__\\n*.pyc\\n.DS_Store\\n",
|
|
473
473
|
},
|
|
474
474
|
],
|
|
475
475
|
notes: "Writes files only (no pip install).",
|
|
@@ -480,18 +480,17 @@ const REGISTRY = {
|
|
|
480
480
|
commands: (ctx) => {
|
|
481
481
|
const projectName = getProjectName(ctx);
|
|
482
482
|
return [
|
|
483
|
-
// Pyramid cookiecutter is common, but basic scaffold:
|
|
484
483
|
{ type: "mkdir", path: "." },
|
|
485
484
|
{
|
|
486
485
|
type: "writeFile",
|
|
487
486
|
path: "requirements.txt",
|
|
488
|
-
content: "pyramid
|
|
487
|
+
content: "pyramid\\nwaitress\\n",
|
|
489
488
|
},
|
|
490
489
|
{
|
|
491
490
|
type: "writeFile",
|
|
492
491
|
path: "app.py",
|
|
493
492
|
content:
|
|
494
|
-
"from wsgiref.simple_server import make_server
|
|
493
|
+
"from wsgiref.simple_server import make_server\\nfrom pyramid.config import Configurator\\nfrom pyramid.response import Response\\n\\ndef hello_world(request):\\n return Response('Hello World!')\\n\\nif __name__ == '__main__':\\n with Configurator() as config:\\n config.add_route('hello', '/')\\n config.add_view(hello_world, route_name='hello')\\n app = config.make_wsgi_app()\\n server = make_server('0.0.0.0', 6543, app)\\n server.serve_forever()\\n",
|
|
495
494
|
},
|
|
496
495
|
];
|
|
497
496
|
},
|
|
@@ -534,8 +533,6 @@ const REGISTRY = {
|
|
|
534
533
|
commands: (ctx) => {
|
|
535
534
|
const projectName = getProjectName(ctx);
|
|
536
535
|
const pm = getPackageManager(ctx); // usually npm for tauri frontend
|
|
537
|
-
// Using create-tauri-app via pmExec
|
|
538
|
-
// cargo create-tauri-app is also an option but node way is common if JS frontend
|
|
539
536
|
return [pmExec(pm, "create-tauri-app@latest", [projectName])];
|
|
540
537
|
},
|
|
541
538
|
notes: "Cross-platform desktop app",
|
|
@@ -551,8 +548,6 @@ const REGISTRY = {
|
|
|
551
548
|
args: ["init", "--name", projectName],
|
|
552
549
|
cwdFromProjectRoot: true,
|
|
553
550
|
},
|
|
554
|
-
// In reality, one would use cargo-leptos or a template.
|
|
555
|
-
// Just a stub for now.
|
|
556
551
|
];
|
|
557
552
|
},
|
|
558
553
|
notes: "Init basic Rust project (Leptos needs template usually)",
|
|
@@ -591,7 +586,7 @@ const REGISTRY = {
|
|
|
591
586
|
type: "writeFile",
|
|
592
587
|
path: "main.go",
|
|
593
588
|
content:
|
|
594
|
-
'package main
|
|
589
|
+
'package main\\n\\nimport "fmt"\\n\\nfunc main() {\\n fmt.Println("hello")\\n}\\n',
|
|
595
590
|
},
|
|
596
591
|
];
|
|
597
592
|
},
|
|
@@ -783,8 +778,6 @@ int main() {
|
|
|
783
778
|
id: "java.springboot.maven",
|
|
784
779
|
label: "Spring Boot (Maven)",
|
|
785
780
|
commands: (ctx) => {
|
|
786
|
-
// Simple archetype or just hints. Spring Init is complex.
|
|
787
|
-
// Let's use maven quickstart for now as basic.
|
|
788
781
|
const projectName = getProjectName(ctx);
|
|
789
782
|
return [
|
|
790
783
|
{
|
|
@@ -819,11 +812,8 @@ int main() {
|
|
|
819
812
|
"--project-name",
|
|
820
813
|
projectName,
|
|
821
814
|
],
|
|
822
|
-
cwd: projectName,
|
|
823
|
-
|
|
824
|
-
// runSteps implementation check:
|
|
825
|
-
// It uses `cwdFromProjectRoot` or defaults to current process.cwd().
|
|
826
|
-
// Better to just run gradle init inside the folder.
|
|
815
|
+
cwd: projectName,
|
|
816
|
+
cwdFromProjectRoot: true,
|
|
827
817
|
},
|
|
828
818
|
];
|
|
829
819
|
},
|