kontyra-cli 1.0.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/index.js ADDED
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { execSync } = require('child_process');
6
+
7
+ const cyan = (text) => `\x1b[36m${text}\x1b[0m`;
8
+ const green = (text) => `\x1b[32m${text}\x1b[0m`;
9
+ const red = (text) => `\x1b[31m${text}\x1b[0m`;
10
+
11
+ const projectName = process.argv[2];
12
+
13
+ if (!projectName) {
14
+ console.log(red('Please specify the project directory:'));
15
+ console.log(` npx create-kontyra-app ${cyan('<project-directory>')}`);
16
+ process.exit(1);
17
+ }
18
+
19
+ const targetPath = path.resolve(process.cwd(), projectName);
20
+
21
+ if (fs.existsSync(targetPath)) {
22
+ console.log(red(`Directory ${projectName} already exists. Please choose a different name.`));
23
+ process.exit(1);
24
+ }
25
+
26
+ console.log(`Creating a new Kontyra app in ${green(targetPath)}.\n`);
27
+
28
+ fs.mkdirSync(targetPath, { recursive: true });
29
+
30
+ // Copy the template directory
31
+ const templatePath = path.join(__dirname, 'template');
32
+ if (fs.existsSync(templatePath)) {
33
+ fs.cpSync(templatePath, targetPath, { recursive: true });
34
+ }
35
+
36
+ // Generate package.json
37
+ const packageJson = {
38
+ name: projectName,
39
+ version: "0.1.0",
40
+ private: true,
41
+ scripts: {
42
+ "dev": "node build.js && node server.js",
43
+ "build": "node build.js",
44
+ "start": "node server.js"
45
+ },
46
+ dependencies: {
47
+ "express": "^4.19.0",
48
+ "react": "^18.3.0",
49
+ "react-dom": "^18.3.0",
50
+ "react-router-dom": "^6.22.3"
51
+ },
52
+ devDependencies: {
53
+ "esbuild": "^0.20.0"
54
+ }
55
+ };
56
+
57
+ fs.writeFileSync(
58
+ path.join(targetPath, 'package.json'),
59
+ JSON.stringify(packageJson, null, 2)
60
+ );
61
+
62
+ console.log(green('Project created successfully!\n'));
63
+ console.log('Inside that directory, you can run several commands:');
64
+ console.log(cyan(' npm install'));
65
+ console.log(' Installs the dependencies.\n');
66
+ console.log(cyan(' npm run dev'));
67
+ console.log(' Starts the development server with SSR.\n');
68
+ console.log('We suggest that you begin by typing:');
69
+ console.log(cyan(` cd ${projectName}`));
70
+ console.log(cyan(' npm install'));
71
+ console.log(cyan(' npm run dev\n'));
72
+ console.log('Happy coding with Kontyra!');
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "kontyra-cli",
3
+ "version": "1.0.0",
4
+ "description": "CLI tool to scaffold a new Kontyra Framework application.",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "kontyra-cli": "index.js"
8
+ },
9
+ "scripts": {
10
+ "test": "echo \"Error: no test specified\" && exit 1"
11
+ },
12
+ "keywords": [
13
+ "kontyra",
14
+ "framework",
15
+ "react",
16
+ "ssr",
17
+ "scaffold"
18
+ ],
19
+ "author": "Kontyra",
20
+ "license": "MIT",
21
+ "dependencies": {
22
+ "chalk": "^4.1.2"
23
+ }
24
+ }
@@ -0,0 +1,103 @@
1
+ const esbuild = require('esbuild');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+
5
+ const PAGES_DIR = path.join(__dirname, 'src', 'pages');
6
+
7
+ // 1. Scan pages directory
8
+ const files = fs.readdirSync(PAGES_DIR).filter(f => f.endsWith('.kon'));
9
+
10
+ // 2. Generate the React Router setup dynamically
11
+ let imports = `import React from 'react';\n`;
12
+ imports += `import Layout from './src/components/Layout.kon';\n`;
13
+ let routes = '';
14
+
15
+ files.forEach(file => {
16
+ const componentName = file.replace('.kon', '');
17
+ // index.kon maps to '/', about.kon maps to '/about'
18
+ const routePath = componentName === 'index' ? '/' : `/${componentName}`;
19
+
20
+ imports += `import ${componentName}Page from './src/pages/${file}';\n`;
21
+ routes += ` <Route path="${routePath}" element={<${componentName}Page />} />\n`;
22
+ });
23
+
24
+ const clientEntryCode = `
25
+ ${imports}
26
+ import { hydrateRoot } from 'react-dom/client';
27
+ import { BrowserRouter, Routes, Route } from 'react-router-dom';
28
+
29
+ function App() {
30
+ return (
31
+ <BrowserRouter>
32
+ <Layout>
33
+ <Routes>
34
+ ${routes}
35
+ </Routes>
36
+ </Layout>
37
+ </BrowserRouter>
38
+ );
39
+ }
40
+
41
+ hydrateRoot(document.getElementById('root'), <App />);
42
+ `;
43
+
44
+ const serverEntryCode = `
45
+ ${imports}
46
+ import { StaticRouter } from 'react-router-dom/server';
47
+ import { Routes, Route } from 'react-router-dom';
48
+
49
+ export function AppServer({ location }) {
50
+ return (
51
+ <StaticRouter location={location}>
52
+ <Layout>
53
+ <Routes>
54
+ ${routes}
55
+ </Routes>
56
+ </Layout>
57
+ </StaticRouter>
58
+ );
59
+ }
60
+ `;
61
+
62
+ // Write the dynamic entry files
63
+ fs.writeFileSync(path.join(__dirname, '.client-entry.jsx'), clientEntryCode);
64
+ fs.writeFileSync(path.join(__dirname, '.server-entry.jsx'), serverEntryCode);
65
+
66
+ // Custom plugin to handle .kon files as JSX
67
+ const kontyraPlugin = {
68
+ name: 'kontyra-plugin',
69
+ setup(build) {
70
+ build.onLoad({ filter: /\.kon$/ }, async (args) => {
71
+ const contents = await fs.promises.readFile(args.path, 'utf8');
72
+ return { contents, loader: 'jsx' };
73
+ });
74
+ },
75
+ };
76
+
77
+ const commonConfig = {
78
+ bundle: true,
79
+ plugins: [kontyraPlugin],
80
+ loader: { '.js': 'jsx', '.jsx': 'jsx' },
81
+ define: { 'process.env.NODE_ENV': '"development"' },
82
+ };
83
+
84
+ // Build Client
85
+ esbuild.build({
86
+ ...commonConfig,
87
+ entryPoints: ['.client-entry.jsx'],
88
+ outfile: 'public/dist/client.js',
89
+ }).then(() => {
90
+ console.log('Client build successful!');
91
+ }).catch(() => process.exit(1));
92
+
93
+ // Build Server
94
+ esbuild.build({
95
+ ...commonConfig,
96
+ entryPoints: ['.server-entry.jsx'],
97
+ outfile: 'dist/server-app.js',
98
+ platform: 'node',
99
+ format: 'cjs',
100
+ external: ['react', 'react-dom', 'react-router-dom', 'react-router'],
101
+ }).then(() => {
102
+ console.log('Server build successful!');
103
+ }).catch(() => process.exit(1));