├── README.md ├── composer.json └── src ├── FileSystem.php ├── FileSystemInterface.php ├── ModuleLoader.php └── ModuleNotFoundException.php /README.md: -------------------------------------------------------------------------------- 1 | # V8Js ModuleLoader 2 | 3 | [![Build Status](https://travis-ci.org/chenos/v8js-module-loader.svg?branch=master)](https://travis-ci.org/chenos/v8js-module-loader) [![Coverage Status](https://coveralls.io/repos/github/chenos/v8js-module-loader/badge.svg?branch=master)](https://coveralls.io/github/chenos/v8js-module-loader?branch=master) 4 | 5 | ## Requirements 6 | 7 | - PHP 7.0+ 8 | - V8Js extension 2.0+ 9 | 10 | ## Installation 11 | 12 | ```sh 13 | composer require chenos/v8js-module-loader 14 | ``` 15 | 16 | ## Dependents 17 | 18 | - [chenos/execjs](https://github.com/chenos/execjs) 19 | 20 | ## Testing 21 | 22 | ``` 23 | make test 24 | ``` 25 | 26 | ## Example 27 | 28 | ```php 29 | make example 30 | ``` 31 | 32 | Access http://127.0.0.1:8888 33 | 34 | ## Usage 35 | 36 | ```php 37 | use Chenos\V8JsModuleLoader\ModuleLoader; 38 | 39 | // entry directory 40 | $loader = new ModuleLoader(__DIR__); 41 | 42 | $loader->setExtensions('.js', '.json'); 43 | 44 | $loader->setEntryDir(__DIR__); 45 | 46 | // array 47 | $loader->addOverride(['vue' => 'vue/dist/vue.runtime.common.js']); 48 | 49 | // key, value 50 | $loader->addOverride('vue', 'vue/dist/vue.runtime.common.js'); 51 | 52 | // v8js version > 2.1.0+ 53 | $loader->addOverride(['fn' => function (...$args) {}]); 54 | $loader->addOverride('obj', new stdClass()); 55 | 56 | $loader->addVendorDir(__DIR__.'/node_modules', __DIR__.'/bower_components'); 57 | 58 | $v8 = new V8Js(); 59 | 60 | $v8->setModuleNormaliser([$loader, 'normaliseIdentifier']); 61 | $v8->setModuleLoader([$loader, 'loadModule']); 62 | ``` 63 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chenos/v8js-module-loader", 3 | "require": { 4 | "webmozart/path-util": "^2.3" 5 | }, 6 | "require-dev": { 7 | "phpunit/phpunit": "^6.5", 8 | "php-coveralls/php-coveralls": "^2.0" 9 | }, 10 | "autoload": { 11 | "psr-4": { 12 | "Chenos\\V8JsModuleLoader\\": "src" 13 | } 14 | }, 15 | "autoload-dev": { 16 | "psr-4": { 17 | "Chenos\\V8JsModuleLoader\\Tests\\": "tests" 18 | } 19 | }, 20 | "scripts": { 21 | "test": "phpunit --colors=always", 22 | "test-coverage": "phpunit --colors=always --coverage-clover clover.xml", 23 | "coveralls": "php-coveralls -v" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/FileSystem.php: -------------------------------------------------------------------------------- 1 | setEntryDir($entryDir ?: getcwd()); 24 | $this->setFileSystem( 25 | $filesystem instanceof FileSystemInterface 26 | ? $filesystem : new FileSystem()); 27 | } 28 | 29 | public function addOverride($name, $override = null) 30 | { 31 | if (is_array($name)) { 32 | $this->overrides = array_merge($this->overrides, $name); 33 | } elseif (func_num_args() == 2) { 34 | $this->overrides[$name] = $override; 35 | } 36 | 37 | return $this; 38 | } 39 | 40 | public function addVendorDir(...$vendorDirs) 41 | { 42 | $this->vendorDirs = array_merge( 43 | $this->vendorDirs, $vendorDirs); 44 | 45 | return $this; 46 | } 47 | 48 | public function setEntryDir($entryDir) 49 | { 50 | $this->entryDir = $entryDir; 51 | 52 | return $this; 53 | } 54 | 55 | public function setExtensions(...$extensions) 56 | { 57 | $this->extensions = $extensions; 58 | 59 | return $this; 60 | } 61 | 62 | public function setFileSystem(FileSystemInterface $filesystem) 63 | { 64 | $this->fs = $filesystem; 65 | 66 | return $this; 67 | } 68 | 69 | public function normaliseIdentifier($base, $moduleName) 70 | { 71 | if (isset($this->overrides[$moduleName])) { 72 | if (is_object($this->overrides[$moduleName])) { 73 | return ['', $moduleName]; 74 | } 75 | $moduleName = $this->overrides[$moduleName]; 76 | } 77 | 78 | if (strpos($moduleName, '.') !== 0 && strpos($moduleName, '/') !== 0) { 79 | foreach ($this->vendorDirs as $dir) { 80 | if ($file = $this->getModuleFile($dir, $moduleName)) { 81 | return [$this->fs->dirname($file), $this->fs->filename($file)]; 82 | } 83 | } 84 | 85 | return ['', $moduleName]; 86 | } 87 | 88 | if (strpos($moduleName, '/') === 0) { 89 | $file = $this->getModuleFile($moduleName); 90 | } elseif (strpos($base, '/') === 0) { 91 | $file = $this->getModuleFile($this->fs->pathJoin($base, $moduleName)); 92 | } else { 93 | $file = $this->getModuleFile($this->fs->pathJoin($this->entryDir, $base, $moduleName)); 94 | } 95 | 96 | if (! $file) { 97 | throw new ModuleNotFoundException("Cannot find module '$moduleName'"); 98 | } 99 | 100 | return [$this->fs->dirname($file), $this->fs->filename($file)]; 101 | } 102 | 103 | public function loadModule($moduleName) 104 | { 105 | if (! isset($this->overrides[$moduleName])) { 106 | if (strpos($moduleName, '/') !== 0) { 107 | $moduleName = implode('/', $this->normaliseIdentifier('', $moduleName)); 108 | } 109 | 110 | return $this->fs->exists($moduleName) ? $this->fs->get($moduleName) : null; 111 | } 112 | 113 | return $this->overrides[$moduleName]; 114 | } 115 | 116 | public function getModuleFile($path) 117 | { 118 | if (func_num_args() > 1) { 119 | $path = $this->fs->pathJoin(func_get_args()); 120 | } 121 | 122 | if (isset($this->pathCache[$path])) { 123 | return $this->pathCache[$path]; 124 | } 125 | 126 | if ($this->fs->isFile($path)) { 127 | return $this->pathCache[$path] = $path; 128 | } 129 | 130 | if ($this->fs->exists($this->fs->pathJoin($path, 'package.json'))) { 131 | $package = $this->fs->get($this->fs->pathJoin($path, 'package.json')); 132 | if (isset($package->main)) { 133 | return $this->pathCache[$path] = $this->getModuleFile($path, $package->main); 134 | } 135 | } 136 | 137 | foreach ($this->extensions as $extension) { 138 | if ($this->fs->exists($path.$extension)) { 139 | return $this->pathCache[$path] = $path.$extension; 140 | } 141 | } 142 | 143 | foreach ($this->extensions as $extension) { 144 | if ($this->fs->exists("{$path}/index{$extension}")) { 145 | return $this->pathCache[$path] = "{$path}/index{$extension}"; 146 | } 147 | } 148 | 149 | return false; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/ModuleNotFoundException.php: -------------------------------------------------------------------------------- 1 |