create-jen-app 0.1.0 → 0.1.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/dist/colors.js ADDED
@@ -0,0 +1,92 @@
1
+ /*
2
+ * This file is part of Jen.js.
3
+ * Copyright (C) 2026 oopsio
4
+ *
5
+ * This program is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ */
18
+ // ANSI color codes for beautiful terminal output
19
+ export const colors = {
20
+ // Main colors
21
+ primary: (str) => `\x1b[38;2;99;102;241m${str}\x1b[0m`, // Indigo
22
+ accent: (str) => `\x1b[38;2;139;92;246m${str}\x1b[0m`, // Violet
23
+ success: (str) => `\x1b[38;2;34;197;94m${str}\x1b[0m`, // Green
24
+ warning: (str) => `\x1b[38;2;251;146;60m${str}\x1b[0m`, // Orange
25
+ error: (str) => `\x1b[38;2;239;68;68m${str}\x1b[0m`, // Red
26
+ // Utility colors
27
+ cyan: (str) => `\x1b[38;2;34;211;238m${str}\x1b[0m`,
28
+ magenta: (str) => `\x1b[38;2;219;39;119m${str}\x1b[0m`,
29
+ yellow: (str) => `\x1b[38;2;250;204;21m${str}\x1b[0m`,
30
+ // Text styles
31
+ bold: (str) => `\x1b[1m${str}\x1b[0m`,
32
+ dim: (str) => `\x1b[2m${str}\x1b[0m`,
33
+ italic: (str) => `\x1b[3m${str}\x1b[0m`,
34
+ underline: (str) => `\x1b[4m${str}\x1b[0m`,
35
+ // Background colors (dark theme)
36
+ bgDark: (str) => `\x1b[48;2;23;23;23m${str}\x1b[0m`,
37
+ bgPrimary: (str) => `\x1b[48;2;99;102;241m${str}\x1b[0m`,
38
+ // Reset
39
+ reset: "\x1b[0m",
40
+ };
41
+ export const symbols = {
42
+ arrow: "→",
43
+ check: "✓",
44
+ cross: "✕",
45
+ dot: "•",
46
+ star: "★",
47
+ sparkles: "✨",
48
+ rocket: "🚀",
49
+ folder: "📁",
50
+ package: "📦",
51
+ code: "💻",
52
+ };
53
+ export function printBanner() {
54
+ const banner = `
55
+ ${colors.accent(colors.bold(`
56
+ ██╗███████╗███╗ ██╗ █████╗ ██████╗ ██████╗
57
+ ██║██╔════╝████╗ ██║ ██╔══██╗██╔══██╗██╔══██╗
58
+ ██║█████╗ ██╔██╗ ██║ ███████║██████╔╝██████╔╝
59
+ ██║██╔══╝ ██║╚██╗██║ ██╔══██║██╔═══╝ ██╔═══╝
60
+ ██║███████╗██║ ╚████║ ██║ ██║██║ ██║
61
+ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝
62
+ `))}
63
+
64
+ ${colors.primary(colors.bold("Create a beautiful Jen.js application"))}
65
+ ${colors.dim("v1.0.0")}
66
+ `;
67
+ console.log(banner);
68
+ }
69
+ export function printSection(title) {
70
+ console.log(`\n${colors.primary(colors.bold(title))}`);
71
+ }
72
+ export function printSubsection(title) {
73
+ console.log(`${colors.accent(" " + title)}`);
74
+ }
75
+ export function printSuccess(message) {
76
+ console.log(`${colors.success(symbols.check)} ${message}`);
77
+ }
78
+ export function printInfo(message) {
79
+ console.log(`${colors.cyan("ℹ")} ${message}`);
80
+ }
81
+ export function printStep(step, total, message) {
82
+ console.log(`${colors.primary(`[${step}/${total}]`)} ${colors.bold(message)}`);
83
+ }
84
+ export function printCode(code) {
85
+ console.log(`\n${colors.dim(" " + code)}\n`);
86
+ }
87
+ export function printNext(steps) {
88
+ console.log(`\n${colors.accent(colors.bold("Next steps:"))}`);
89
+ steps.forEach((step, i) => {
90
+ console.log(` ${colors.primary(i + 1 + ".")} ${step}`);
91
+ });
92
+ }
package/dist/create.js ADDED
@@ -0,0 +1,167 @@
1
+ /*
2
+ * This file is part of Jen.js.
3
+ * Copyright (C) 2026 oopsio
4
+ *
5
+ * This program is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ */
18
+ import fs from "fs";
19
+ import path from "path";
20
+ import { fileURLToPath } from "url";
21
+ import pc from "picocolors";
22
+ import { intro, outro, text, confirm, select, cancel, isCancel, note, spinner, } from "@clack/prompts";
23
+ import { copyTemplateFiles, createProjectFiles } from "./generator.js";
24
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
25
+ function validateProjectName(val) {
26
+ if (!val)
27
+ return "Project name is required";
28
+ if (!/^[a-zA-Z0-9._-]+$/.test(val)) {
29
+ return "Project name can only contain alphanumeric characters, dots, dashes and underscores";
30
+ }
31
+ return undefined;
32
+ }
33
+ export async function createJenApp() {
34
+ intro(pc.cyan(pc.bold("Jen.js")) + pc.dim(" - create app"));
35
+ // Get project name from CLI args or prompt
36
+ let projectName = process.argv[2];
37
+ // @ts-nocheck
38
+ if (!projectName) {
39
+ const res = await text({
40
+ message: "Project name",
41
+ placeholder: "my-jen-app",
42
+ defaultValue: "my-jen-app",
43
+ validate: validateProjectName,
44
+ });
45
+ if (isCancel(res)) {
46
+ cancel(pc.dim("Cancelled"));
47
+ process.exit(0);
48
+ }
49
+ projectName = res;
50
+ }
51
+ const projectDir = path.resolve(process.cwd(), projectName);
52
+ // Check if directory exists
53
+ if (fs.existsSync(projectDir)) {
54
+ const overwrite = await confirm({
55
+ message: `${pc.yellow(projectName)} already exists. Overwrite?`,
56
+ initialValue: false,
57
+ });
58
+ if (isCancel(overwrite)) {
59
+ cancel(pc.dim("Cancelled"));
60
+ process.exit(0);
61
+ }
62
+ if (!overwrite) {
63
+ cancel(pc.dim("Cancelled"));
64
+ process.exit(0);
65
+ }
66
+ fs.rmSync(projectDir, { recursive: true, force: true });
67
+ }
68
+ note("Configuring your project", pc.magenta("Setup"));
69
+ // Template selection
70
+ const template = await select({
71
+ message: "Select a template",
72
+ options: [
73
+ {
74
+ label: `${pc.cyan("Static")} - Pure SSG with components`,
75
+ value: "static",
76
+ hint: "Fast, lightweight static sites",
77
+ },
78
+ ],
79
+ });
80
+ if (isCancel(template)) {
81
+ cancel(pc.dim("Cancelled"));
82
+ process.exit(0);
83
+ }
84
+ // TypeScript
85
+ const typescript = await confirm({
86
+ message: "Use TypeScript?",
87
+ initialValue: true,
88
+ });
89
+ if (isCancel(typescript)) {
90
+ cancel(pc.dim("Cancelled"));
91
+ process.exit(0);
92
+ }
93
+ // Deps installation
94
+ const installDeps = await confirm({
95
+ message: "Install dependencies?",
96
+ initialValue: true,
97
+ });
98
+ if (isCancel(installDeps)) {
99
+ cancel(pc.dim("Cancelled"));
100
+ process.exit(0);
101
+ }
102
+ // Git initialization
103
+ const gitInit = await confirm({
104
+ message: "Initialize git repository?",
105
+ initialValue: true,
106
+ });
107
+ if (isCancel(gitInit)) {
108
+ cancel(pc.dim("Cancelled"));
109
+ process.exit(0);
110
+ }
111
+ const options = {
112
+ projectName,
113
+ template,
114
+ typescript,
115
+ installDeps,
116
+ gitInit,
117
+ };
118
+ note("Creating project files", pc.green("Generator"));
119
+ // Spinner for progress
120
+ const s = spinner();
121
+ // Create project structure
122
+ s.start("Setting up directories");
123
+ fs.mkdirSync(projectDir, { recursive: true });
124
+ s.stop(pc.green("Directories created"));
125
+ // Copy template files
126
+ s.start("Copying template files");
127
+ const templateDir = path.join(__dirname, "..", "templates", options.template);
128
+ if (fs.existsSync(templateDir)) {
129
+ copyTemplateFiles(templateDir, projectDir);
130
+ }
131
+ s.stop(pc.green("Template files copied"));
132
+ // Create project files
133
+ s.start("Generating configuration files");
134
+ createProjectFiles(projectDir, options);
135
+ s.stop(pc.green("Configuration files generated"));
136
+ // Git init
137
+ if (options.gitInit) {
138
+ s.start("Initializing git repository");
139
+ try {
140
+ const { execSync } = await import("child_process");
141
+ execSync("git init", { cwd: projectDir, stdio: "pipe" });
142
+ fs.writeFileSync(path.join(projectDir, ".gitignore"), `node_modules/
143
+ dist/
144
+ .jen/
145
+ .env
146
+ .env.local
147
+ .DS_Store
148
+ *.log
149
+ `);
150
+ s.stop(pc.green("Git repository initialized"));
151
+ }
152
+ catch {
153
+ s.stop(pc.yellow("Git initialization skipped"));
154
+ }
155
+ }
156
+ outro(pc.green(pc.bold("✨ Your Jen.js app is ready!")));
157
+ const nextSteps = [
158
+ pc.cyan(`cd ${projectName}`),
159
+ installDeps
160
+ ? pc.cyan("npm run dev") + pc.dim(" # start dev server")
161
+ : pc.cyan("npm install") + pc.dim(" # then npm run dev"),
162
+ ];
163
+ console.log("\n" + pc.bold("Next steps:"));
164
+ for (const step of nextSteps)
165
+ console.log(" " + pc.dim("• ") + step);
166
+ console.log("\n" + pc.dim("Happy coding! 🎉") + "\n");
167
+ }
@@ -0,0 +1,149 @@
1
+ /*
2
+ * This file is part of Jen.js.
3
+ * Copyright (C) 2026 oopsio
4
+ *
5
+ * This program is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ */
18
+ import fs from "fs";
19
+ import path from "path";
20
+ export function copyTemplateFiles(src, dest) {
21
+ if (!fs.existsSync(src)) {
22
+ return;
23
+ }
24
+ const files = fs.readdirSync(src);
25
+ for (const file of files) {
26
+ const srcPath = path.join(src, file);
27
+ const destPath = path.join(dest, file);
28
+ const stat = fs.statSync(srcPath);
29
+ if (stat.isDirectory()) {
30
+ fs.mkdirSync(destPath, { recursive: true });
31
+ copyTemplateFiles(srcPath, destPath);
32
+ }
33
+ else {
34
+ fs.copyFileSync(srcPath, destPath);
35
+ }
36
+ }
37
+ }
38
+ export function createProjectFiles(dir, options) {
39
+ // Read template's package.json if it exists
40
+ let templatePackageJson = {};
41
+ const templatePackagePath = path.join(dir, "package.json");
42
+ if (fs.existsSync(templatePackagePath)) {
43
+ const content = fs.readFileSync(templatePackagePath, "utf-8");
44
+ templatePackageJson = JSON.parse(content);
45
+ }
46
+ // Merge with user project name
47
+ const packageJson = {
48
+ ...templatePackageJson,
49
+ name: options.projectName.toLowerCase().replace(/\s+/g, "-"),
50
+ version: "0.1.0",
51
+ type: "module",
52
+ scripts: {
53
+ ...templatePackageJson.scripts,
54
+ dev: "jen dev",
55
+ build: "jen build",
56
+ start: "jen start",
57
+ ...(options.typescript && { typecheck: "tsc --noEmit" }),
58
+ },
59
+ dependencies: {
60
+ ...templatePackageJson.dependencies,
61
+ "@jenjs/master": "^1.2.5",
62
+ },
63
+ devDependencies: {
64
+ ...templatePackageJson.devDependencies,
65
+ ...(options.typescript && {
66
+ "@types/node": "^22.10.0",
67
+ typescript: "^5.7.2",
68
+ }),
69
+ },
70
+ };
71
+ fs.writeFileSync(path.join(dir, "package.json"), JSON.stringify(packageJson, null, 2));
72
+ // Create tsconfig.json if TypeScript
73
+ if (options.typescript) {
74
+ const tsconfig = {
75
+ compilerOptions: {
76
+ target: "ES2022",
77
+ module: "ESNext",
78
+ moduleResolution: "node",
79
+ strict: true,
80
+ jsx: "react-jsx",
81
+ jsxImportSource: "preact",
82
+ lib: ["ES2022", "DOM", "DOM.Iterable"],
83
+ skipLibCheck: true,
84
+ forceConsistentCasingInFileNames: true,
85
+ resolveJsonModule: true,
86
+ allowImportingTsExtensions: true,
87
+ },
88
+ include: ["site/**/*"],
89
+ exclude: ["node_modules", "dist"],
90
+ };
91
+ fs.writeFileSync(path.join(dir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2));
92
+ }
93
+ // Create README
94
+ const readme = `# ${options.projectName}
95
+
96
+ A beautiful Jen.js application.
97
+
98
+ ## Getting Started
99
+
100
+ \`\`\`bash
101
+ npm install
102
+ npm run dev
103
+ \`\`\`
104
+
105
+ ## Available Commands
106
+
107
+ - \`npm run dev\` - Start development server (http://localhost:3000)
108
+ - \`npm run build\` - Build for production
109
+ - \`npm run start\` - Start production server
110
+ ${options.typescript ? "- \`npm run typecheck\` - Check TypeScript types\n" : ""}
111
+
112
+ ## Project Structure
113
+
114
+ \`\`\`
115
+ src/
116
+ ├── styles/ # Global styles
117
+ ├── components/ # Preact components
118
+ └── routes/ # Page routes
119
+ dist/ # Build output
120
+ jen.config.ts # Jen.js configuration
121
+ \`\`\`
122
+
123
+ ## Learn More
124
+
125
+ - [Jen.js Documentation](https://github.com/kessud2021/Jen.js)
126
+ - [Preact Documentation](https://preactjs.com)
127
+
128
+ ## License
129
+
130
+ MIT
131
+ `;
132
+ fs.writeFileSync(path.join(dir, "README.md"), readme);
133
+ // Create .env.example
134
+ const envExample = `# Database
135
+ DATABASE_URL=
136
+
137
+ # API
138
+ API_SECRET=
139
+
140
+ # Environment
141
+ NODE_ENV=development
142
+ `;
143
+ fs.writeFileSync(path.join(dir, ".env.example"), envExample);
144
+ // Create directory structure
145
+ const dirs = ["site/styles", "site/components", "site/routes", "site/assets"];
146
+ for (const dir_path of dirs) {
147
+ fs.mkdirSync(path.join(dir, dir_path), { recursive: true });
148
+ }
149
+ }
package/dist/index.js CHANGED
@@ -1,72 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import d from"fs";import b from"path";import{fileURLToPath as D}from"url";import m from"prompts";var t={primary:e=>`\x1B[38;2;99;102;241m${e}\x1B[0m`,accent:e=>`\x1B[38;2;139;92;246m${e}\x1B[0m`,success:e=>`\x1B[38;2;34;197;94m${e}\x1B[0m`,warning:e=>`\x1B[38;2;251;146;60m${e}\x1B[0m`,error:e=>`\x1B[38;2;239;68;68m${e}\x1B[0m`,cyan:e=>`\x1B[38;2;34;211;238m${e}\x1B[0m`,magenta:e=>`\x1B[38;2;219;39;119m${e}\x1B[0m`,yellow:e=>`\x1B[38;2;250;204;21m${e}\x1B[0m`,bold:e=>`\x1B[1m${e}\x1B[0m`,dim:e=>`\x1B[2m${e}\x1B[0m`,italic:e=>`\x1B[3m${e}\x1B[0m`,underline:e=>`\x1B[4m${e}\x1B[0m`,bgDark:e=>`\x1B[48;2;23;23;23m${e}\x1B[0m`,bgPrimary:e=>`\x1B[48;2;99;102;241m${e}\x1B[0m`,reset:"\x1B[0m"},f={arrow:"\u2192",check:"\u2713",cross:"\u2715",dot:"\u2022",star:"\u2605",sparkles:"\u2728",rocket:"\u{1F680}",folder:"\u{1F4C1}",package:"\u{1F4E6}",code:"\u{1F4BB}"};function v(){let e=`
3
- ${t.accent(t.bold(`
4
- \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557
5
- \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
6
- \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D
7
- \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u255D
8
- \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551
9
- \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D
10
- `))}
11
-
12
- ${t.primary(t.bold("Create a beautiful Jen.js application"))}
13
- ${t.dim("v1.0.0")}
14
- `;console.log(e)}function j(e){console.log(`
15
- ${t.primary(t.bold(e))}`)}function g(e){console.log(`${t.success(f.check)} ${e}`)}function h(e){console.log(`${t.cyan("\u2139")} ${e}`)}function u(e,n,i){console.log(`${t.primary(`[${e}/${n}]`)} ${t.bold(i)}`)}function w(e){console.log(`
16
- ${t.accent(t.bold("Next steps:"))}`),e.forEach((n,i)=>{console.log(` ${t.primary(i+1+".")} ${n}`)})}import r from"fs";import s from"path";function S(e,n){if(!r.existsSync(e))return;let i=r.readdirSync(e);for(let o of i){let c=s.join(e,o),a=s.join(n,o);r.statSync(c).isDirectory()?(r.mkdirSync(a,{recursive:!0}),S(c,a)):r.copyFileSync(c,a)}}function k(e,n){let i={},o=s.join(e,"package.json");if(r.existsSync(o)){let p=r.readFileSync(o,"utf-8");i=JSON.parse(p)}let c={...i,name:n.projectName.toLowerCase().replace(/\s+/g,"-"),version:"0.1.0",type:"module",scripts:{...i.scripts,dev:"jen dev",build:"jen build",start:"jen start",...n.typescript&&{typecheck:"tsc --noEmit"}},dependencies:{...i.dependencies,"@jenjs/master":"^1.2.5"},devDependencies:{...i.devDependencies,...n.typescript&&{"@types/node":"^22.10.0",typescript:"^5.7.2"}}};if(r.writeFileSync(s.join(e,"package.json"),JSON.stringify(c,null,2)),n.typescript){let p={compilerOptions:{target:"ES2022",module:"ESNext",moduleResolution:"node",strict:!0,jsx:"react-jsx",jsxImportSource:"preact",lib:["ES2022","DOM","DOM.Iterable"],skipLibCheck:!0,forceConsistentCasingInFileNames:!0,resolveJsonModule:!0,allowImportingTsExtensions:!0},include:["site/**/*"],exclude:["node_modules","dist"]};r.writeFileSync(s.join(e,"tsconfig.json"),JSON.stringify(p,null,2))}let a=`# ${n.projectName}
17
-
18
- A beautiful Jen.js application.
19
-
20
- ## Getting Started
21
-
22
- \`\`\`bash
23
- npm install
24
- npm run dev
25
- \`\`\`
26
-
27
- ## Available Commands
28
-
29
- - \`npm run dev\` - Start development server (http://localhost:3000)
30
- - \`npm run build\` - Build for production
31
- - \`npm run start\` - Start production server
32
- ${n.typescript?"- `npm run typecheck` - Check TypeScript types\n":""}
33
-
34
- ## Project Structure
35
-
36
- \`\`\`
37
- src/
38
- \u251C\u2500\u2500 styles/ # Global styles
39
- \u251C\u2500\u2500 components/ # Preact components
40
- \u2514\u2500\u2500 routes/ # Page routes
41
- dist/ # Build output
42
- jen.config.ts # Jen.js configuration
43
- \`\`\`
44
-
45
- ## Learn More
46
-
47
- - [Jen.js Documentation](https://github.com/kessud2021/Jen.js)
48
- - [Preact Documentation](https://preactjs.com)
49
-
50
- ## License
51
-
52
- MIT
53
- `;r.writeFileSync(s.join(e,"README.md"),a),r.writeFileSync(s.join(e,".env.example"),`# Database
54
- DATABASE_URL=
55
-
56
- # API
57
- API_SECRET=
58
-
59
- # Environment
60
- NODE_ENV=development
61
- `);let y=["site/styles","site/components","site/routes","site/assets"];for(let p of y)r.mkdirSync(s.join(e,p),{recursive:!0})}var I=b.dirname(D(import.meta.url));async function P(){v();let e=process.argv[2];e||(e=(await m({type:"text",name:"projectName",message:"Project name",initial:"my-jen-app",validate:$=>$?/^[a-zA-Z0-9._-]+$/.test($)?!0:"Project name can only contain alphanumeric characters, dots, dashes and underscores":"Project name is required"})).projectName);let n=b.resolve(process.cwd(),e);d.existsSync(n)&&((await m({type:"confirm",name:"overwrite",message:`${t.warning(e)} already exists. Overwrite?`,initial:!1})).overwrite||(console.log(`${t.dim("Cancelled")}`),process.exit(0)),d.rmSync(n,{recursive:!0})),j(`${f.sparkles} Configuring your project`);let i=await m({type:"select",name:"template",message:"Select a template",choices:[{title:`${t.accent("Static")} - Pure SSG with components`,value:"static",description:"Fast, lightweight static sites"}]}),o=await m({type:"confirm",name:"typescript",message:"Use TypeScript?",initial:!0}),c=await m({type:"confirm",name:"installDeps",message:"Install dependencies?",initial:!0}),a=await m({type:"confirm",name:"gitInit",message:"Initialize git repository?",initial:!0}),l={projectName:e,template:i.template,typescript:o.typescript,installDeps:c.installDeps,gitInit:a.gitInit};j(`${f.rocket} Creating project`),u(1,4,"Setting up directories"),d.mkdirSync(n,{recursive:!0}),g("Directories created"),u(2,4,"Copying template files");let y=b.join(I,"..","templates",l.template);if(d.existsSync(y)&&S(y,n),g("Template files copied"),u(3,4,"Generating configuration files"),k(n,l),g("Configuration files generated"),l.gitInit){u(4,4,"Initializing git repository");try{let{execSync:x}=await import("child_process");x("git init",{cwd:n,stdio:"pipe"}),d.writeFileSync(b.join(n,".gitignore"),`node_modules/
62
- dist/
63
- .jen/
64
- .env
65
- .env.local
66
- .DS_Store
67
- *.log
68
- `),g("Git repository initialized")}catch{h("Git initialization skipped")}}console.log(`
69
- ${t.accent(t.bold("\u2728 Your Jen.js app is ready!"))}`);let p=[`${t.cyan(`cd ${e}`)}`,l.installDeps?`${t.cyan("npm run dev")} ${t.dim("to start development server")}`:`${t.cyan("npm install")} then ${t.cyan("npm run dev")}`];w(p),console.log(`
70
- ${t.dim("Happy coding! \u{1F389}")}
71
- `)}P().catch(e=>{console.error(`
72
- \u274C Error:`,e.message),process.exit(1)});
2
+ import { createJenApp } from "./create.js";
3
+ createJenApp().catch((error) => {
4
+ console.error("\n❌ Error:", error.message);
5
+ process.exit(1);
6
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-jen-app",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Create a beautiful Jen.js application with a single command",
5
5
  "type": "module",
6
6
  "bin": {
@@ -46,5 +46,5 @@
46
46
  "tsx": "^4.7.0",
47
47
  "typescript": "^5.7.2"
48
48
  },
49
- "gitHead": "d75b257e51249af4f2863c56c8fe8b051bfc6303"
49
+ "gitHead": "fb883341104d6b3fc197930af24182ceccccbdef"
50
50
  }
@@ -8,10 +8,14 @@
8
8
  },
9
9
  "dependencies": {
10
10
  "@jenjs/master": "^1.2.5",
11
+ "@vue/compiler-sfc": "^3.5.28",
11
12
  "esbuild": "^0.25.0",
13
+ "glob": "^13.0.5",
12
14
  "preact": "^10.25.4",
13
15
  "preact-render-to-string": "^6.5.13",
14
- "sirv": "^3.0.1"
16
+ "sass": "^1.97.3",
17
+ "sirv": "^3.0.1",
18
+ "svelte": "^5.51.3"
15
19
  },
16
20
  "devDependencies": {
17
21
  "@types/node": "^22.10.0",