Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
node_modules/
content/*
vendor/
*.log
*.sqlite
*.db
*.zip
yarn.lock
package-lock.json
composer.lock
Expand Down
136 changes: 136 additions & 0 deletions bin/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
const fs = require('fs');
const path = require('path');
const archiver = require('archiver');
const ignore = require('ignore');

// Function to read and parse .gitignore
function getGitignorePatterns(gitignorePath) {
const ig = ignore();
const gitignoreContent = fs.readFileSync(gitignorePath, 'utf-8');
// Split the content by lines and add non-empty, non-comment lines to the ignore patterns
const patterns = gitignoreContent
.split('\n')
.map(line => line.trim()) // Remove whitespace from start and end
.filter(line => line && !line.startsWith('#')); // Remove empty lines and comments

ig.add(patterns);
return ig;
}

// Function to handle files that start with `include/Module` or `include\\Module`
function scanModuleComponent(filePath, ig, filesArray, baseDir) {

const relativePath = path.relative(baseDir, filePath);
const moduleRootPath = path.relative(path.join(baseDir, "include", "Module"), filePath);
const moduleName = moduleRootPath.replace(/(\\|\/).*$/i, '');
const moduleRelativePath = moduleRootPath.replace(moduleName + '\\', '');
const stats = fs.statSync(filePath);
ig.add(['node_modules/', '.git', '.gitignore', '.active', '.git/', 'Assets/src']);

// Check if the file should be excluded based on .gitignore or included based on custom rules
if (ig.ignores(moduleRelativePath)) {
return;
}

if (stats.isDirectory()) {
// Recursively scan subdirectories
scanDirectory(filePath, ig, filesArray, baseDir);
} else {
// Save the relative path for maintaining the folder structure in the ZIP
filesArray.push(relativePath);
}
}

// Function to scan a directory, check against exclusions from .gitignore and custom rules, and collect files
function scanDirectory(dirPath, ig, filesArray, baseDir) {
// Set baseDir to dirPath if not already set
baseDir = baseDir || dirPath;

const files = fs.readdirSync(dirPath);

files.forEach(file => {
const filePath = path.join(dirPath, file);
const relativePath = path.relative(baseDir, filePath);
const stats = fs.statSync(filePath);

// Always include the 'vendor/' folder
if (relativePath.startsWith('vendor') || relativePath.startsWith('.htaccess')) {
filesArray.push(relativePath);
}

// Handle paths starting with `include/Module/` or `include\\Module\\`
if (relativePath.startsWith('include/Module/') || relativePath.startsWith('include\\Module\\')) {
scanModuleComponent(filePath, ig, filesArray, baseDir);
return;
}

// Check if the file should be excluded based on .gitignore or included based on custom rules
if (ig.ignores(relativePath)) {
return;
}

if (stats.isDirectory()) {
// Recursively scan subdirectories
scanDirectory(filePath, ig, filesArray, baseDir);
} else {
// Save the relative path for maintaining the folder structure in the ZIP
filesArray.push(relativePath);
}
});
}

// Function to create a ZIP archive with progress on a single line
function createZip(filesArray, baseDir, outputZipPath) {
const output = fs.createWriteStream(outputZipPath);
const archive = archiver('zip', {
zlib: { level: 9 } // Set the compression level
});

output.on('close', function () {
console.log(`\nZIP archive created successfully. Total bytes: ${archive.pointer()}`);
});

archive.on('error', function (err) {
throw err;
});

archive.on('progress', function (progress) {
const percent = (progress.fs.processedBytes / progress.fs.totalBytes) * 100;
process.stdout.write(`\rProgress: ${percent.toFixed(2)}% (${progress.fs.processedBytes} of ${progress.fs.totalBytes} bytes)`);
});

archive.pipe(output);

filesArray.forEach(relativePath => {
const fullPath = path.join(baseDir, relativePath);
archive.file(fullPath, { name: relativePath });
});

archive.finalize();
}

// Usage
const gitignorePath = path.join('F:/www/MerapiPanel', '.gitignore');
const ig = getGitignorePatterns(gitignorePath); // Get the .gitignore patterns
ig.add([
"node_modules/",
'bin',
'content/',
'schema',
'.*',
'babel.config.json',
'webpack.config.json',
'webpack.config.js',
'composer.json',
'composer.lock',
'package.json',
'package-lock.json',
'env.php'
]);

const filesArray = [];
const directoryToScan = 'F:/www/MerapiPanel';
const outputZipPath = 'F:/www/MerapiPanel/build.zip';

scanDirectory(directoryToScan, ig, filesArray);
createZip(filesArray, directoryToScan, outputZipPath);
2 changes: 1 addition & 1 deletion include/Box.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ protected function initialize()
$this->module_container->initialize();
}

public static function module($name = null): Container|Fragment|Proxy|Module|null
public static function module($name = null): Container|Fragment|Proxy|Module|bool
{
if (!$name || empty($name)) {
return self::$instance->module_container;
Expand Down
9 changes: 6 additions & 3 deletions include/Box/Container.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

namespace MerapiPanel\Box {

use MerapiPanel\Box\Module\AbstractLoader;
Expand Down Expand Up @@ -77,10 +78,12 @@ public function initialize()
public function __get($name)
{
if (empty($this->stack[$name])) {
$this->stack[$name] = $this->loader->loadModule($name, $this);
$module = $this->loader->loadModule($name, $this);
if ($module instanceof Module) {
$this->stack[$name] = $module;
} else return false;
}
return $this->stack[$name];

}

protected array $events = [];
Expand All @@ -91,4 +94,4 @@ public function __on($name, $callback)
$this->events[$name][] = $callback;
}
}
}
}
2 changes: 1 addition & 1 deletion include/Box/Module/AbstractLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ abstract class AbstractLoader

protected string $directory;
abstract function __construct(string $directory);
abstract function loadModule(string $name, Container $container): Module;
abstract function loadModule(string $name, Container $container): Module|bool;
abstract function loadFragment(string $name, Module|Fragment $parent): Fragment|null;
abstract function initialize(Container $container): void;

Expand Down
3 changes: 1 addition & 2 deletions include/Box/Module/Entity/Fragment.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,8 @@ public function getContent()
return $result;
}
} catch (Throwable $t) {
throw $t;
return null;
}
throw new Exception("Could't get content, {$this->path} is not file");
}


Expand Down
12 changes: 2 additions & 10 deletions include/Box/Module/ModuleLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,21 +137,13 @@ function loadFragment(string $name, Module|Fragment $parent): Fragment|null
}


private $couter = [];

function loadModule(string $name, Container $container): Module
function loadModule(string $name, Container $container): Module | bool
{

// if (isset($this->couter[$name])) {
// $this->couter[$name] += 1;
// } else {
// $this->couter[$name] = 1;
// }

$path = Path::join($this->directory, $name);

if (!file_exists($path)) {
throw new Exception("Module not found: $name");
return false;
}
if (!is_dir(Path::join($path, "data"))) mkdir(Path::join($path, "data"));
if (!in_array($name, self::$defaultModules) && !file_exists(Path::join($path, ".active"))) throw new Exception("Module {$name} inactive", 500);
Expand Down
Loading