Skip to content

Commit 6b373c2

Browse files
committed
Initial commit
0 parents  commit 6b373c2

24 files changed

Lines changed: 548 additions & 0 deletions

.gitignore

Whitespace-only changes.

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022 Mihatori Kei
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<div align="center">
2+
<img width="250px" src="codeigniter-vite.svg">
3+
<h1>Codeigniter viteJs</h1>
4+
<p>Vitejs Integration For Codeigniter4</p>
5+
<hr />
6+
<h2>🚧 W.I.P 🚧</h2>
7+
</div>

composer.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "mihtori/codeignitervite",
3+
"description": "Integrte viteJs in codeiginter4 framework",
4+
"license": "MIT",
5+
"authors": [
6+
{
7+
"name": "Mihatori Kei",
8+
"email": "[email protected]",
9+
"homepage": "https://github.com/firtadokei"
10+
}
11+
],
12+
"require": {
13+
"php": "^7.4 || ^8.0"
14+
}
15+
}

src/CodeigniterVite.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
namespace Mihatori\CodeigniterVite;
4+
5+
class CodeigniterVite
6+
{
7+
/**
8+
* Get vite entry file on running or bundled files instead.
9+
*
10+
* @return string single script tag on developing and much more on production
11+
*/
12+
public static function tags()
13+
{
14+
# Check if vite is running.
15+
$entryFile = env('VITE_ORIGIN') . '/' . env('VITE_RESOURCES_DIR') . '/' . env('VITE_ENTRY_FILE');
16+
17+
$result = @file_get_contents($entryFile) ? '<script type="module" src="' . $entryFile . '"></script>' : null;
18+
19+
# React HMR fix.
20+
if (!empty($result))
21+
{
22+
$result = static::getReactTag() . "$result";
23+
}
24+
25+
# If vite isn't running, then return the compiled resources.
26+
if (empty($result) && static::manifest())
27+
{
28+
# Get the manifest content.
29+
$manifest = file_get_contents(static::manifest());
30+
# You look much pretty as an php object =).
31+
$manifest = json_decode($manifest);
32+
33+
# Now, we will get all js files and css from the manifest.
34+
foreach ($manifest as $file)
35+
{
36+
# Js files.
37+
$result .= '<script type="module" src="/' . $file->file . '"></script>';
38+
39+
if (!empty($file->css))
40+
{
41+
foreach ($file->css as $cssFile)
42+
{
43+
$result .= '<link rel="stylesheet" href="/' . $cssFile . '" />';
44+
}
45+
}
46+
}
47+
}
48+
49+
return $result;
50+
}
51+
52+
/**
53+
* Enable HMR for react.
54+
*
55+
* @see https://v2.vitejs.dev/guide/backend-integration.html
56+
*
57+
* @return string|null a simple module script
58+
*/
59+
public static function getReactTag()
60+
{
61+
if (env('VITE_FRAMEWORK') === 'react')
62+
{
63+
$origin = env('VITE_ORIGIN');
64+
$result = "<script type=\"module\">import RefreshRuntime from '$origin/@react-refresh';RefreshRuntime.injectIntoGlobalHook(window);window.\$RefreshReg\$ = () => {};window.\$RefreshSig\$ = () => (type) => type;window.__vite_plugin_react_preamble_installed__ = true;</script>";
65+
return "$result\n\t";
66+
}
67+
68+
return null;
69+
}
70+
71+
/**
72+
* @return string manifest path
73+
*/
74+
private static function manifest()
75+
{
76+
return is_file(FCPATH . 'manifest.json') ? FCPATH . 'manifest.json' : null;
77+
}
78+
}

src/Commands/Init.php

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
<?php
2+
3+
namespace Mihatori\CodeigniterVite\Commands;
4+
5+
use CodeIgniter\CLI\BaseCommand;
6+
use CodeIgniter\CLI\CLI;
7+
use CodeIgniter\Publisher\Publisher;
8+
use Throwable;
9+
10+
class Init extends BaseCommand
11+
{
12+
protected $group = 'Modules';
13+
protected $name = 'vite:init';
14+
protected $description = 'Initialize codeigniter vite module';
15+
16+
/**
17+
* @var string
18+
*/
19+
private string $framework;
20+
21+
22+
/**
23+
* Module path
24+
*
25+
* @var string
26+
*/
27+
private $path;
28+
29+
public function __construct()
30+
{
31+
$this->path = service('autoloader')->getNamespace('Mihatori\\CodeigniterVite')[0];
32+
}
33+
34+
public function run(array $params)
35+
{
36+
# Module start.
37+
CLI::write('Installing Codeigniter Vite Plugin 🔥⚡', 'white', 'cyan');
38+
CLI::newLine();
39+
40+
# Set framework.
41+
$this->framework = $params['framework'] ?? CLI::prompt('Choose a framework: ', ['none', 'vue', 'react', 'svelte']);
42+
CLI::newLine();
43+
44+
# First, what if user select a none supported framework ?!
45+
# if that's true, return an error message with available frameworks.
46+
if (!in_array($this->framework, ['none', 'vue', 'react', 'svelte']))
47+
{
48+
CLI::error("❌ Sorry, but $this->framework is not supported!");
49+
CLI::error('Available frameworks are: ' . CLI::color('vue, react and svelte', 'green'));
50+
CLI::newLine();
51+
return;
52+
}
53+
54+
# Now let's generate vite necesary files (vite.config.js, package.json & resources direction).
55+
$this->generateFrameworkFiles();
56+
57+
# Update .env file.
58+
$this->updateEnvFile();
59+
60+
# Everything is ready now.
61+
CLI::write('Codeigniter vite has succussfuly installed ✅', 'green');
62+
CLI::newLine();
63+
CLI::write('run: npm install && npm run dev');
64+
CLI::newLine();
65+
}
66+
67+
/**
68+
* Generate vite files (vite.config.js, package.json & resources)
69+
*
70+
* @return void
71+
*/
72+
private function generateFrameworkFiles()
73+
{
74+
CLI::write('⚡ Generating vite files...', 'yellow');
75+
CLI::newLine();
76+
77+
# Framework files.
78+
$paths = ['vite.config.js', 'package.json', 'resources'];
79+
80+
if ($this->framework === 'none')
81+
{
82+
$publisher = new Publisher($this->path . 'Config/default', ROOTPATH);
83+
}
84+
else
85+
{
86+
$publisher = new Publisher($this->path . "Config/$this->framework", ROOTPATH);
87+
}
88+
89+
# Publish them.
90+
try
91+
{
92+
$publisher->addPaths($paths)->merge(true);
93+
}
94+
catch (Throwable $e)
95+
{
96+
$this->showError($e);
97+
return;
98+
}
99+
100+
CLI::write('Vite files are ready ✅', 'green');
101+
CLI::newLine();
102+
}
103+
104+
/**
105+
* Set vite configs in .env file
106+
*
107+
* @return void
108+
*/
109+
private function updateEnvFile()
110+
{
111+
CLI::write('Updating .env file...', 'yellow');
112+
113+
# Get the env file.
114+
$envFile = ROOTPATH . '.env';
115+
116+
# Does exist? if not, generate it =)
117+
if (is_file($envFile))
118+
{
119+
# But first, let's take a backup.
120+
copy($envFile, $envFile . 'BACKUP-' . time());
121+
122+
# Get .env.default content
123+
$content = file_get_contents($this->path . 'Config/env.default');
124+
125+
# Append it.
126+
file_put_contents($envFile, "\n\n$content", FILE_APPEND);
127+
}
128+
else
129+
{
130+
# As we said before, generate it.
131+
copy($this->path . 'Config/env.default', ROOTPATH . '.env');
132+
}
133+
134+
# Define framework.
135+
if ($this->framework !== 'none')
136+
{
137+
$updates = file_get_contents($envFile);
138+
$updates = str_replace("VITE_FRAMEWORK='none'", "VITE_FRAMEWORK='$this->framework'", $updates);
139+
file_put_contents($envFile, $updates);
140+
}
141+
142+
# env updated.
143+
CLI::newLine();
144+
CLI::write('.env file updated ✅', 'green');
145+
CLI::newLine();
146+
}
147+
}

src/Config/Registrar.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Mihatori\CodeigniterVite\Config;
4+
5+
class Registrar
6+
{
7+
public static function View(): array
8+
{
9+
return [
10+
'decorators' => ['Mihatori\CodeigniterVite\Decorator'],
11+
];
12+
}
13+
}

src/Config/default/package.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "codeigniter-vite",
3+
"private": true,
4+
"version": "0.0.0",
5+
"scripts": {
6+
"dev": "vite",
7+
"build": "vite build",
8+
"preview": "vite preview"
9+
},
10+
"devDependencies": {
11+
"vite": "^2.9.13"
12+
}
13+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// Be creative =)

src/Config/default/vite.config.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { defineConfig, loadEnv } from 'vite'
2+
import path from 'path'
3+
4+
export default defineConfig(() => {
5+
6+
const env = loadEnv(null, process.cwd())
7+
8+
return {
9+
plugins: [],
10+
11+
build: {
12+
emptyOutDir: false,
13+
outDir: './public/',
14+
assetsDir: env.VITE_BUILD_DIR,
15+
manifest: true,
16+
rollupOptions: {
17+
input: `./${env.VITE_RESOURCES_DIR}/${env.VITE_ENTRY_FILE}`
18+
}
19+
},
20+
21+
server: {
22+
origin: env.VITE_ORIGIN,
23+
port: env.VITE_PORT,
24+
strictPort: true,
25+
hmr: true
26+
},
27+
28+
resolve: {
29+
alias: {
30+
'@': path.resolve(__dirname, `./${env.VITE_RESOURCES_DIR}`)
31+
}
32+
}
33+
}
34+
})

0 commit comments

Comments
 (0)