From 1085be50b55f3e62686c108e9c5b385cdd086a6a Mon Sep 17 00:00:00 2001 From: Luke Towers Date: Thu, 10 Feb 2022 16:10:07 -0600 Subject: [PATCH 1/9] Implement autoregistration of Laravel Mix packages for modules, plugins, & themes. Also renamed default to winter.mix.js instead of winter-mix.js started on the mix:install support. Refs: #440, #401. --- composer.json | 6 + modules/system/ServiceProvider.php | 2 +- .../{winter-mix.js => winter.mix.js} | 0 modules/system/classes/MixAssets.php | 137 ++++++++++++++---- modules/system/console/MixInstall.php | 12 ++ modules/system/console/MixList.php | 14 ++ .../console/fixtures/winter.mix.js.fixture | 4 + 7 files changed, 145 insertions(+), 30 deletions(-) rename modules/system/assets/js/snowboard/{winter-mix.js => winter.mix.js} (100%) create mode 100644 modules/system/console/fixtures/winter.mix.js.fixture diff --git a/composer.json b/composer.json index 4f7c896b5e..7b6061435d 100644 --- a/composer.json +++ b/composer.json @@ -83,5 +83,11 @@ "replace": false, "merge-dev": false } + }, + "config": { + "allow-plugins": { + "composer/installers": true, + "wikimedia/composer-merge-plugin": true + } } } diff --git a/modules/system/ServiceProvider.php b/modules/system/ServiceProvider.php index 47afc3c252..bffd0eca18 100644 --- a/modules/system/ServiceProvider.php +++ b/modules/system/ServiceProvider.php @@ -570,7 +570,7 @@ protected function registerAssetBundles() }); MixAssets::registerCallback(function ($mix) { - $mix->registerPackage('snowboard', '~/modules/system/assets/js/snowboard'); + $mix->registerPackage('snowboard', '~/modules/system/assets/js/snowboard/winter.mix.js'); }); } diff --git a/modules/system/assets/js/snowboard/winter-mix.js b/modules/system/assets/js/snowboard/winter.mix.js similarity index 100% rename from modules/system/assets/js/snowboard/winter-mix.js rename to modules/system/assets/js/snowboard/winter.mix.js diff --git a/modules/system/classes/MixAssets.php b/modules/system/classes/MixAssets.php index a06d2038b6..2a232c797d 100644 --- a/modules/system/classes/MixAssets.php +++ b/modules/system/classes/MixAssets.php @@ -1,8 +1,11 @@ 'winter-mix.js', + * 'package-name-1' => 'winter.mix.js', * 'package-name-2' => 'assets/js/build.js', + * 'package-name-3' => 'assets/css', // winter.mix.js is assumed to be the config file in this path * ]; * } */ @@ -72,26 +83,69 @@ public function init() } foreach ($packageArray as $name => $package) { - $this->registerPackage($name, PluginManager::instance()->getPluginPath($pluginCode), $package); + $this->registerPackage($name, PluginManager::instance()->getPluginPath($pluginCode) . '/' . $package); } } } - // Allow current theme to define mix assets - $theme = Theme::getActiveTheme(); + // Get the currently enabled modules + $enabledModules = Config::get('cms.loadModules', []); + + if (in_array('Cms', $enabledModules)) { + // Allow current theme to define mix assets + $theme = Theme::getActiveTheme(); + + if (!is_null($theme)) { + $mix = $theme->getConfigValue('mix', []); - if (!is_null($theme)) { - $mix = $theme->getConfigValue('mix', []); + if (count($mix)) { + foreach ($mix as $name => $file) { + $this->registerPackage($name, $theme->getPath() . '/' . $file); + } + } + } + } + + $packagePaths = []; + + // Search modules for Mix packages to autoregister + foreach ($enabledModules as $module) { + $module = strtolower($module); + $path = base_path("modules/$module") . '/' . $this->mixJs; + if (File::exists($path)) { + $packagePaths["module-$module"] = $path; + } + } - if (count($mix)) { - foreach ($mix as $name => $file) { - $path = PathResolver::resolve($theme->getPath() . '/' . $file); - $pinfo = pathinfo($path); + // Search plugins for Mix packages to autoregister + $plugins = PluginManager::instance()->getPlugins(); + foreach ($plugins as $plugin) { + $path = $plugin->getPluginPath() . '/' . $this->mixJs; + if (File::exists($path)) { + $packagePaths[$plugin->getPluginIdentifier()] = $path; + } + } - $this->registerPackage($name, $pinfo['dirname'], $pinfo['basename']); + // Search themes for Mix packages to autoregister + if (in_array('Cms', $enabledModules)) { + $themes = Theme::all(); + foreach ($themes as $theme) { + $path = $theme->getPath() . '/' . $this->mixJs; + if (File::exists($path)) { + $packagePaths["theme-" . $theme->getId()] = $path; } } } + + // Register the autodiscovered Mix packages + foreach ($packagePaths as $package => $path) { + try { + $this->registerPackage($package, $path); + } catch (SystemException $e) { + // Either the package name or the mixJs path have already been registered, skip. + continue; + } + } } /** @@ -135,6 +189,7 @@ public function getPackageCount() */ public function getPackages() { + ksort($this->packages); return $this->packages; } @@ -146,40 +201,64 @@ public function getPackages() * The name of the package is an alias that can be used to reference this package in other methods within this * class. * - * By default, the MixAssets class will look for a `package.json` file for Node dependencies, and a ` + * By default, the MixAssets class will look for a `package.json` file for Node dependencies, and a `winter.mix.js` + * file for the Laravel Mix configuration * - * @param string $name - * @param string $path - * @param string $packageJson - * @param string $mixJson + * @param string $name The name of the package being registered + * @param string $path The path to the Mix JS configuration file. If there is a related package.json file then it is + * required to be present in the same directory as the winter.mix.js file * @return void */ - public function registerPackage($name, $path, $mixJs = 'winter-mix.js') + public function registerPackage($name, $path) { - // Require JS file for $mixJs + // Symbolize the path + $path = File::symbolizePath($path); + + // Normalize the arguments + $resolvedPath = PathResolver::resolve($path); + $pinfo = pathinfo($resolvedPath); + $path = $pinfo['dirname']; + $mixJs = $pinfo['basename']; + + // Require $mixJs to be a JS file $extension = File::extension($mixJs); if ($extension !== 'js') { - throw new ApplicationException( + throw new SystemException( sprintf('The mix configuration for package "%s" must be a JavaScript file ending with .js', $name) ); } - $path = rtrim(File::symbolizePath($path), '/\\'); - if (!File::exists($path . DIRECTORY_SEPARATOR . $this->packageJson)) { - throw new ApplicationException( - sprintf('Missing file "%s" in path "%s" for package "%s"', $this->packageJson, $path, $name) + // Check that the package path exists + if (!File::exists($path)) { + throw new SystemException( + sprintf('Cannot register "%s" as a Mix package; the "%s" path does not exist.', $name, $path) ); } - if (!File::exists($path . DIRECTORY_SEPARATOR . $mixJs)) { - throw new ApplicationException( - sprintf('Missing file "%s" in path "%s" for package "%s"', $mixJs, $path, $name) + + // Check for any existing packages already registered under the provided name + if (isset($this->packages[$name])) { + throw new SystemException( + sprintf('Cannot register "%s" as a Mix package; it has already been registered at %s.', $name, $this->packages[$name]['mix']) ); } + $package = "$path/{$this->packageJson}"; + $mix = "$path/$mixJs"; + + // Check for any existing package that already registers the given Mix path + foreach ($this->packages as $packageName => $config) { + if ($config['mix'] === $mix) { + throw new SystemException( + sprintf('Cannot register "%s" (%s) as a Mix package; it has already been registered as %s.', $name, $mix, $packageName) + ); + } + } + + // Register the package $this->packages[$name] = [ 'path' => $path, - 'package' => $path . DIRECTORY_SEPARATOR . $this->packageJson, - 'mix' => $path . DIRECTORY_SEPARATOR . $mixJs, + 'package' => $package, + 'mix' => $mix, ]; } } diff --git a/modules/system/console/MixInstall.php b/modules/system/console/MixInstall.php index f5591172c6..d619186434 100644 --- a/modules/system/console/MixInstall.php +++ b/modules/system/console/MixInstall.php @@ -1,5 +1,6 @@ $package) { + // Detect missing winter.mix.js files and install them + if (!File::exists($package['mix'])) { + $this->info( + sprintf('No Mix file found for %s, creating one at %s...', $name, $package['mix']) + ); + File::put($package['mix'], File::get(__DIR__ . 'fixtures/winter.mix.js.fixture')); + } + + // @TODO: Integrate with the workspaces property and have some form of attachDefaultDependencies + // to load in the Laravel mix dependencies at least somewhere in the chain if required. + $this->info( sprintf('Installing dependencies for package "%s"', $name) ); diff --git a/modules/system/console/MixList.php b/modules/system/console/MixList.php index 6f4d077980..c220c2927b 100644 --- a/modules/system/console/MixList.php +++ b/modules/system/console/MixList.php @@ -1,5 +1,6 @@ info('Packages registered:'); $this->line(''); + $errors = []; + foreach ($packages as $name => $package) { $this->info($name); $this->line(' Path: ' . $package['path']); $this->line(' Configuration: ' . $package['mix']); + + if (!File::exists($package['mix'])) { + $errors[] = "The mix file for $name doesn't exist, try running artisan mix:install"; + } } $this->line(''); + + if (!empty($errors)) { + foreach ($errors as $error) { + $this->error($error); + } + } + return 0; } } diff --git a/modules/system/console/fixtures/winter.mix.js.fixture b/modules/system/console/fixtures/winter.mix.js.fixture new file mode 100644 index 0000000000..6d63c799d3 --- /dev/null +++ b/modules/system/console/fixtures/winter.mix.js.fixture @@ -0,0 +1,4 @@ +const mix = require('laravel-mix'); +mix.setPublicPath(__dirname + '/assets'); + +// Your mix configuration below \ No newline at end of file From b2de281815f82404a6d2dce248f921ecdf5e2031 Mon Sep 17 00:00:00 2001 From: Luke Towers Date: Fri, 11 Feb 2022 13:18:00 -0600 Subject: [PATCH 2/9] Support installing previously unregistered Mix packages for valid modules, themes, & plugins. --- modules/system/classes/MixAssets.php | 1 + modules/system/console/MixInstall.php | 66 +++++++++++++++++++++++---- 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/modules/system/classes/MixAssets.php b/modules/system/classes/MixAssets.php index 2a232c797d..9dabc33763 100644 --- a/modules/system/classes/MixAssets.php +++ b/modules/system/classes/MixAssets.php @@ -215,6 +215,7 @@ public function registerPackage($name, $path) $path = File::symbolizePath($path); // Normalize the arguments + $name = strtolower($name); $resolvedPath = PathResolver::resolve($path); $pinfo = pathinfo($resolvedPath); $path = $pinfo['dirname']; diff --git a/modules/system/console/MixInstall.php b/modules/system/console/MixInstall.php index d619186434..3b30e10482 100644 --- a/modules/system/console/MixInstall.php +++ b/modules/system/console/MixInstall.php @@ -1,9 +1,13 @@ fireCallbacks(); - $packages = $mixedAssets->getPackages(); + $registeredPackages = $mixedAssets->getPackages(); + $requestedPackages = $this->option('package') ?: []; - if (count($this->option('package')) && count($packages)) { - foreach (array_keys($packages) as $name) { - if (!in_array($name, $this->option('package'))) { - unset($packages[$name]); + if (count($requestedPackages) && count($registeredPackages)) { + $availablePackages = array_keys($registeredPackages); + $cmsEnabled = in_array('Cms', Config::get('cms.loadModules')); + + // Autogenerate config files for packages that don't exist but can be autodiscovered + foreach ($requestedPackages as $package) { + // Normalize the package name + $package = strtolower($package); + + // Check if the package is already registered + if (in_array($package, $availablePackages)) { + continue; + } + + // Check if package could be a module (but explicitly ignore core Winter modules) + if (Str::startsWith($package, 'module-') && !in_array($package, ['system', 'backend', 'cms'])) { + $mixedAssets->registerPackage($package, base_path('modules/' . Str::after($package, 'module-') . '/winter.mix.js')); + continue; + } + + // Check if package could be a theme + if ( + $cmsEnabled + && Str::startsWith($package, 'theme-') + && Theme::exists(Str::after($package, 'theme-')) + ) { + $theme = Theme::load(Str::after($package, 'theme-')); + $mixedAssets->registerPackage($package, $theme->getPath() . '/winter.mix.js'); + continue; + } + + // Check if a package could be a plugin + if (PluginManager::instance()->exists($package)) { + $mixedAssets->registerPackage($package, PluginManager::instance()->getPluginPath($package) . '/winter.mix.js'); + continue; + } + + + } + + // Get an updated list of packages including any newly added packages + $registeredPackages = $mixedAssets->getPackages(); + + // Filter the registered packages to only deal with the requested packages + foreach (array_keys($registeredPackages) as $name) { + if (!in_array($name, $requestedPackages)) { + unset($registeredPackages[$name]); } } } - if (!count($packages)) { - if (count($this->option('package'))) { + if (!count($registeredPackages)) { + if (count($requestedPackages)) { $this->error('No registered packages matched the requested packages for installation.'); return 1; } else { @@ -71,13 +119,13 @@ public function handle(): int } // Process each package - foreach ($packages as $name => $package) { + foreach ($registeredPackages as $name => $package) { // Detect missing winter.mix.js files and install them if (!File::exists($package['mix'])) { $this->info( sprintf('No Mix file found for %s, creating one at %s...', $name, $package['mix']) ); - File::put($package['mix'], File::get(__DIR__ . 'fixtures/winter.mix.js.fixture')); + File::put($package['mix'], File::get(__DIR__ . '/fixtures/winter.mix.js.fixture')); } // @TODO: Integrate with the workspaces property and have some form of attachDefaultDependencies From 1cbbd6474d74b0b93f3f86819d64d3a67bc7766f Mon Sep 17 00:00:00 2001 From: Luke Towers Date: Fri, 11 Feb 2022 14:20:10 -0600 Subject: [PATCH 3/9] Use relative paths in the MixAssets manager --- modules/system/classes/MixAssets.php | 4 ++-- modules/system/classes/PluginManager.php | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/system/classes/MixAssets.php b/modules/system/classes/MixAssets.php index 9dabc33763..beaa9345cc 100644 --- a/modules/system/classes/MixAssets.php +++ b/modules/system/classes/MixAssets.php @@ -4,7 +4,7 @@ use Config; use SystemException; use Cms\Classes\Theme; -use Winter\Storm\Support\Arr; +use Winter\Storm\Support\Str; use System\Classes\PluginManager; use Winter\Storm\Filesystem\PathResolver; @@ -218,7 +218,7 @@ public function registerPackage($name, $path) $name = strtolower($name); $resolvedPath = PathResolver::resolve($path); $pinfo = pathinfo($resolvedPath); - $path = $pinfo['dirname']; + $path = Str::after($pinfo['dirname'], base_path() . '/'); $mixJs = $pinfo['basename']; // Require $mixJs to be a JS file diff --git a/modules/system/classes/PluginManager.php b/modules/system/classes/PluginManager.php index fd15082967..669c1c98e6 100644 --- a/modules/system/classes/PluginManager.php +++ b/modules/system/classes/PluginManager.php @@ -370,6 +370,7 @@ public function bootPlugin($plugin) public function getPluginPath($id) { $classId = $this->getIdentifier($id); + $classId = $this->normalizeIdentifier($classId); if (!isset($this->pathMap[$classId])) { return null; } From 236ac3929ffd1b7079a89e635ff648b47fe5dc8a Mon Sep 17 00:00:00 2001 From: Luke Towers Date: Fri, 11 Feb 2022 14:20:56 -0600 Subject: [PATCH 4/9] Add modification of package.json to mix:install and TTY passthrough support --- modules/system/console/MixInstall.php | 95 ++++++++++++++++++++------- 1 file changed, 73 insertions(+), 22 deletions(-) diff --git a/modules/system/console/MixInstall.php b/modules/system/console/MixInstall.php index 3b30e10482..d47eb1c4b7 100644 --- a/modules/system/console/MixInstall.php +++ b/modules/system/console/MixInstall.php @@ -8,6 +8,7 @@ use Symfony\Component\Process\Process; use System\Classes\MixAssets; use System\Classes\PluginManager; +use Symfony\Component\Process\Exception\ProcessSignaledException; class MixInstall extends Command { @@ -57,15 +58,21 @@ public function handle(): int $registeredPackages = $mixedAssets->getPackages(); $requestedPackages = $this->option('package') ?: []; + // Normalize the requestedPackages option + if (count($requestedPackages)) { + foreach ($requestedPackages as &$name) { + $name = strtolower($name); + } + unset($name); + } + + // Filter the registered packages to only include requested packages if (count($requestedPackages) && count($registeredPackages)) { $availablePackages = array_keys($registeredPackages); $cmsEnabled = in_array('Cms', Config::get('cms.loadModules')); // Autogenerate config files for packages that don't exist but can be autodiscovered foreach ($requestedPackages as $package) { - // Normalize the package name - $package = strtolower($package); - // Check if the package is already registered if (in_array($package, $availablePackages)) { continue; @@ -93,8 +100,6 @@ public function handle(): int $mixedAssets->registerPackage($package, PluginManager::instance()->getPluginPath($package) . '/winter.mix.js'); continue; } - - } // Get an updated list of packages including any newly added packages @@ -118,6 +123,15 @@ public function handle(): int } } + // Load the main package.json for the project + $canModifyPackageJson = null; + $packageJsonPath = base_path('package.json'); + $packageJson = []; + if (File::exists($packageJsonPath)) { + $packageJson = json_decode(File::get($packageJsonPath), true); + } + $workspacesPackages = $packageJson['workspaces']['packages'] ?? []; + // Process each package foreach ($registeredPackages as $name => $package) { // Detect missing winter.mix.js files and install them @@ -128,21 +142,41 @@ public function handle(): int File::put($package['mix'], File::get(__DIR__ . '/fixtures/winter.mix.js.fixture')); } - // @TODO: Integrate with the workspaces property and have some form of attachDefaultDependencies - // to load in the Laravel mix dependencies at least somewhere in the chain if required. + // Add the package path to the instance's package.json->workspaces->packages property if not present + if (!in_array($package['path'], $workspacesPackages)) { + if (!isset($canModifyPackageJson)) { + if ($this->confirm('package.json will be modified. Continue?', true)) { + $canModifyPackageJson = true; + } else { + $canModifyPackageJson = false; + break; + } + } - $this->info( - sprintf('Installing dependencies for package "%s"', $name) - ); - if ($this->installPackageDeps($package) !== 0) { - $this->error( - sprintf('Unable to install dependencies for package "%s"', $name) - ); - } else { $this->info( - sprintf('Package "%s" dependencies installed.', $name) + sprintf('Adding %s (%s) to the workspaces.packages property in package.json', $name, $package['path']) ); + $workspacesPackages = array_merge($workspacesPackages, [$package['path']]); } + + // @TODO: Integrate with the workspaces property and have some form of attachDefaultDependencies + // to load in the Laravel mix dependencies at least somewhere in the chain if required. + } + + // Modify the package.json file if required + if ($canModifyPackageJson) { + asort($workspacesPackages); + $packageJson['workspaces']['packages'] = array_values($workspacesPackages); + File::put($packageJsonPath, json_encode($packageJson, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); + + // Ensure separation between package.json modification messages and rest of output + $this->info(''); + } + + if ($this->installPackageDeps() !== 0) { + $this->error('Unable to install dependencies.'); + } else { + $this->info('Dependencies successfully installed!'); } return 0; @@ -151,18 +185,35 @@ public function handle(): int /** * Installs the dependencies for the given package. * - * @param string $package * @return int */ - protected function installPackageDeps($package) + protected function installPackageDeps() { $command = $this->argument('npmArgs') ?? []; array_unshift($command, 'npm', 'i'); - $process = new Process($command, $package['path']); - $process->run(function ($status, $stdout) { - $this->getOutput()->write($stdout); - }); + $process = new Process($command, base_path()); + + // Attempt to set tty mode, catch and warn with the exception message if unsupported + try { + $process->setTty(true); + } catch (\Throwable $e) { + $this->warn($e->getMessage()); + } + + try { + return $process->run(function ($status, $stdout) { + $this->getOutput()->write($stdout); + }); + } catch (ProcessSignaledException $e) { + if (extension_loaded('pcntl') && $e->getSignal() !== SIGINT) { + throw $e; + } + + return 1; + } + + $this->info(''); return $process->getExitCode(); } From cdfae4abd1b33eaea1f1359fdcdbe734a81c1972 Mon Sep 17 00:00:00 2001 From: Luke Towers Date: Fri, 11 Feb 2022 14:42:51 -0600 Subject: [PATCH 5/9] Automatically add laravel-mix as a package.json dependency if desired --- modules/system/console/MixInstall.php | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/modules/system/console/MixInstall.php b/modules/system/console/MixInstall.php index d47eb1c4b7..33ba4d89e4 100644 --- a/modules/system/console/MixInstall.php +++ b/modules/system/console/MixInstall.php @@ -37,6 +37,11 @@ class MixInstall extends Command */ protected $npmPath = 'npm'; + /** + * @var string Default version of Laravel Mix to install + */ + protected $defaultMixVersion = '^6.0.41'; + /** * Execute the console command. * @return int @@ -132,6 +137,18 @@ public function handle(): int } $workspacesPackages = $packageJson['workspaces']['packages'] ?? []; + // Check to see if Laravel Mix is already present as a dependency + if ( + ( + !isset($packageJson['dependencies']['laravel-mix']) + || !isset($packageJson['devDependencies']['laravel-mix']) + ) + && $this->confirm('laravel-mix was not found as a dependency in package.json, would you like to add it?', true) + ) { + $canModifyPackageJson = true; + $packageJson['devDependencies'] = array_merge($packageJson['devDependencies'] ?? [], ['laravel-mix' => $this->defaultMixVersion]); + } + // Process each package foreach ($registeredPackages as $name => $package) { // Detect missing winter.mix.js files and install them @@ -158,9 +175,6 @@ public function handle(): int ); $workspacesPackages = array_merge($workspacesPackages, [$package['path']]); } - - // @TODO: Integrate with the workspaces property and have some form of attachDefaultDependencies - // to load in the Laravel mix dependencies at least somewhere in the chain if required. } // Modify the package.json file if required From b3dc49f64919f5245aa5b824dbd52a9f253c1a71 Mon Sep 17 00:00:00 2001 From: Luke Towers Date: Fri, 11 Feb 2022 15:37:53 -0600 Subject: [PATCH 6/9] Remove usage of DIRECTORY_SEPERATOR, Windows supports both separators so this it was unnecessary. --- modules/system/console/MixCompile.php | 13 +++++++------ modules/system/console/MixWatch.php | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/modules/system/console/MixCompile.php b/modules/system/console/MixCompile.php index 3c70639081..511de8ad03 100644 --- a/modules/system/console/MixCompile.php +++ b/modules/system/console/MixCompile.php @@ -36,6 +36,7 @@ public function handle(): int $mixedAssets = MixAssets::instance(); $mixedAssets->fireCallbacks(); + // @TODO: support changes from mix:install and MixAssets $packages = $mixedAssets->getPackages(); if (count($this->option('package')) && count($packages)) { @@ -105,16 +106,16 @@ protected function createCommand($package) $command = $this->argument('webpackArgs') ?? []; array_unshift( $command, - $package['path'] . implode(DIRECTORY_SEPARATOR, ['', 'node_modules', 'webpack', 'bin', 'webpack.js']), + $package['path'] . implode('/', ['', 'node_modules', 'webpack', 'bin', 'webpack.js']), '--progress', - '--config=' . $package['path'] . DIRECTORY_SEPARATOR . 'mix.webpack.js' + '--config=' . $package['path'] . '/mix.webpack.js' ); return $command; } protected function createWebpackConfig($path, $mixPath) { - $fixture = File::get(__DIR__ . DIRECTORY_SEPARATOR . 'fixtures' . DIRECTORY_SEPARATOR . 'mix.webpack.js.fixture'); + $fixture = File::get(__DIR__ . '/fixtures/mix.webpack.js.fixture'); $config = str_replace( ['%base%', '%notificationInject%', '%mixConfigPath%'], @@ -122,13 +123,13 @@ protected function createWebpackConfig($path, $mixPath) $fixture ); - File::put($path . DIRECTORY_SEPARATOR . 'mix.webpack.js', $config); + File::put($path . '/mix.webpack.js', $config); } protected function removeWebpackConfig($path) { - if (File::exists($path . DIRECTORY_SEPARATOR . 'mix.webpack.js')) { - File::delete($path . DIRECTORY_SEPARATOR . 'mix.webpack.js'); + if (File::exists($path . '/mix.webpack.js')) { + File::delete($path . '/mix.webpack.js'); } } } diff --git a/modules/system/console/MixWatch.php b/modules/system/console/MixWatch.php index 19ad06aca9..2be721d25b 100644 --- a/modules/system/console/MixWatch.php +++ b/modules/system/console/MixWatch.php @@ -65,7 +65,7 @@ protected function createCommand($package) protected function createWebpackConfig($path, $mixPath) { - $fixture = File::get(__DIR__ . DIRECTORY_SEPARATOR . 'fixtures' . DIRECTORY_SEPARATOR . 'mix.webpack.js.fixture'); + $fixture = File::get(__DIR__ . '/fixtures/mix.webpack.js.fixture'); $config = str_replace( ['%base%', '%notificationInject%', '%mixConfigPath%'], @@ -73,6 +73,6 @@ protected function createWebpackConfig($path, $mixPath) $fixture ); - File::put($path . DIRECTORY_SEPARATOR . 'mix.webpack.js', $config); + File::put($path . '/mix.webpack.js', $config); } } From 6808a7a698dbdd64f7bd58d9de5a9a548178ea72 Mon Sep 17 00:00:00 2001 From: Luke Towers Date: Sat, 12 Feb 2022 09:54:36 -0600 Subject: [PATCH 7/9] Fix mix:compile & mix:watch commands Also added additional checks to improve developer experience when running the commands. --- .../snowboard/build/snowboard.base.debug.js | 2 +- .../js/snowboard/build/snowboard.base.js | 2 +- .../js/snowboard/build/snowboard.extras.js | 2 +- .../js/snowboard/build/snowboard.request.js | 2 +- modules/system/console/MixCompile.php | 134 ++++++++++++++---- modules/system/console/MixInstall.php | 2 +- modules/system/console/MixWatch.php | 31 +++- .../console/fixtures/mix.webpack.js.fixture | 5 +- 8 files changed, 141 insertions(+), 39 deletions(-) diff --git a/modules/system/assets/js/snowboard/build/snowboard.base.debug.js b/modules/system/assets/js/snowboard/build/snowboard.base.debug.js index 9caadec1e1..5ab4e90740 100644 --- a/modules/system/assets/js/snowboard/build/snowboard.base.debug.js +++ b/modules/system/assets/js/snowboard/build/snowboard.base.debug.js @@ -1,3 +1,3 @@ -!function(){var t={9662:function(t,e,n){var r=n(7854),o=n(614),i=n(6330),s=r.TypeError;t.exports=function(t){if(o(t))return t;throw s(i(t)+" is not a function")}},6077:function(t,e,n){var r=n(7854),o=n(614),i=r.String,s=r.TypeError;t.exports=function(t){if("object"==typeof t||o(t))return t;throw s("Can't set "+i(t)+" as a prototype")}},1223:function(t,e,n){var r=n(5112),o=n(30),i=n(3070),s=r("unscopables"),c=Array.prototype;null==c[s]&&i.f(c,s,{configurable:!0,value:o(null)}),t.exports=function(t){c[s][t]=!0}},9670:function(t,e,n){var r=n(7854),o=n(111),i=r.String,s=r.TypeError;t.exports=function(t){if(o(t))return t;throw s(i(t)+" is not an object")}},1318:function(t,e,n){var r=n(5656),o=n(1400),i=n(6244),s=function(t){return function(e,n,s){var c,a=r(e),u=i(a),f=o(s,u);if(t&&n!=n){for(;u>f;)if((c=a[f++])!=c)return!0}else for(;u>f;f++)if((t||f in a)&&a[f]===n)return t||f||0;return!t&&-1}};t.exports={includes:s(!0),indexOf:s(!1)}},4326:function(t,e,n){var r=n(1702),o=r({}.toString),i=r("".slice);t.exports=function(t){return i(o(t),8,-1)}},9920:function(t,e,n){var r=n(2597),o=n(3887),i=n(1236),s=n(3070);t.exports=function(t,e,n){for(var c=o(e),a=s.f,u=i.f,f=0;f0&&r[0]<4?1:+(r[0]+r[1])),!o&&s&&(!(r=s.match(/Edge\/(\d+)/))||r[1]>=74)&&(r=s.match(/Chrome\/(\d+)/))&&(o=+r[1]),t.exports=o},748:function(t){t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},2109:function(t,e,n){var r=n(7854),o=n(1236).f,i=n(8880),s=n(1320),c=n(3505),a=n(9920),u=n(4705);t.exports=function(t,e){var n,f,l,h,p,g=t.target,d=t.global,b=t.stat;if(n=d?r:b?r[g]||c(g,{}):(r[g]||{}).prototype)for(f in e){if(h=e[f],l=t.noTargetGet?(p=o(n,f))&&p.value:n[f],!u(d?f:g+(b?".":"#")+f,t.forced)&&void 0!==l){if(typeof h==typeof l)continue;a(h,l)}(t.sham||l&&l.sham)&&i(h,"sham",!0),s(n,f,h,t)}}},7293:function(t){t.exports=function(t){try{return!!t()}catch(t){return!0}}},4374:function(t,e,n){var r=n(7293);t.exports=!r((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")}))},6916:function(t,e,n){var r=n(4374),o=Function.prototype.call;t.exports=r?o.bind(o):function(){return o.apply(o,arguments)}},6530:function(t,e,n){var r=n(9781),o=n(2597),i=Function.prototype,s=r&&Object.getOwnPropertyDescriptor,c=o(i,"name"),a=c&&"something"===function(){}.name,u=c&&(!r||r&&s(i,"name").configurable);t.exports={EXISTS:c,PROPER:a,CONFIGURABLE:u}},1702:function(t,e,n){var r=n(4374),o=Function.prototype,i=o.bind,s=o.call,c=r&&i.bind(s,s);t.exports=r?function(t){return t&&c(t)}:function(t){return t&&function(){return s.apply(t,arguments)}}},5005:function(t,e,n){var r=n(7854),o=n(614),i=function(t){return o(t)?t:void 0};t.exports=function(t,e){return arguments.length<2?i(r[t]):r[t]&&r[t][e]}},8173:function(t,e,n){var r=n(9662);t.exports=function(t,e){var n=t[e];return null==n?void 0:r(n)}},7854:function(t,e,n){var r=function(t){return t&&t.Math==Math&&t};t.exports=r("object"==typeof globalThis&&globalThis)||r("object"==typeof window&&window)||r("object"==typeof self&&self)||r("object"==typeof n.g&&n.g)||function(){return this}()||Function("return this")()},2597:function(t,e,n){var r=n(1702),o=n(7908),i=r({}.hasOwnProperty);t.exports=Object.hasOwn||function(t,e){return i(o(t),e)}},3501:function(t){t.exports={}},490:function(t,e,n){var r=n(5005);t.exports=r("document","documentElement")},4664:function(t,e,n){var r=n(9781),o=n(7293),i=n(317);t.exports=!r&&!o((function(){return 7!=Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},8361:function(t,e,n){var r=n(7854),o=n(1702),i=n(7293),s=n(4326),c=r.Object,a=o("".split);t.exports=i((function(){return!c("z").propertyIsEnumerable(0)}))?function(t){return"String"==s(t)?a(t,""):c(t)}:c},2788:function(t,e,n){var r=n(1702),o=n(614),i=n(5465),s=r(Function.toString);o(i.inspectSource)||(i.inspectSource=function(t){return s(t)}),t.exports=i.inspectSource},9909:function(t,e,n){var r,o,i,s=n(8536),c=n(7854),a=n(1702),u=n(111),f=n(8880),l=n(2597),h=n(5465),p=n(6200),g=n(3501),d="Object already initialized",b=c.TypeError,v=c.WeakMap;if(s||h.state){var y=h.state||(h.state=new v),w=a(y.get),m=a(y.has),O=a(y.set);r=function(t,e){if(m(y,t))throw new b(d);return e.facade=t,O(y,t,e),e},o=function(t){return w(y,t)||{}},i=function(t){return m(y,t)}}else{var S=p("state");g[S]=!0,r=function(t,e){if(l(t,S))throw new b(d);return e.facade=t,f(t,S,e),e},o=function(t){return l(t,S)?t[S]:{}},i=function(t){return l(t,S)}}t.exports={set:r,get:o,has:i,enforce:function(t){return i(t)?o(t):r(t,{})},getterFor:function(t){return function(e){var n;if(!u(e)||(n=o(e)).type!==t)throw b("Incompatible receiver, "+t+" required");return n}}}},614:function(t){t.exports=function(t){return"function"==typeof t}},4705:function(t,e,n){var r=n(7293),o=n(614),i=/#|\.prototype\./,s=function(t,e){var n=a[c(t)];return n==f||n!=u&&(o(e)?r(e):!!e)},c=s.normalize=function(t){return String(t).replace(i,".").toLowerCase()},a=s.data={},u=s.NATIVE="N",f=s.POLYFILL="P";t.exports=s},111:function(t,e,n){var r=n(614);t.exports=function(t){return"object"==typeof t?null!==t:r(t)}},1913:function(t){t.exports=!1},2190:function(t,e,n){var r=n(7854),o=n(5005),i=n(614),s=n(7976),c=n(3307),a=r.Object;t.exports=c?function(t){return"symbol"==typeof t}:function(t){var e=o("Symbol");return i(e)&&s(e.prototype,a(t))}},3383:function(t,e,n){"use strict";var r,o,i,s=n(7293),c=n(614),a=n(30),u=n(9518),f=n(1320),l=n(5112),h=n(1913),p=l("iterator"),g=!1;[].keys&&("next"in(i=[].keys())?(o=u(u(i)))!==Object.prototype&&(r=o):g=!0),null==r||s((function(){var t={};return r[p].call(t)!==t}))?r={}:h&&(r=a(r)),c(r[p])||f(r,p,(function(){return this})),t.exports={IteratorPrototype:r,BUGGY_SAFARI_ITERATORS:g}},7497:function(t){t.exports={}},6244:function(t,e,n){var r=n(7466);t.exports=function(t){return r(t.length)}},133:function(t,e,n){var r=n(7392),o=n(7293);t.exports=!!Object.getOwnPropertySymbols&&!o((function(){var t=Symbol();return!String(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&r&&r<41}))},8536:function(t,e,n){var r=n(7854),o=n(614),i=n(2788),s=r.WeakMap;t.exports=o(s)&&/native code/.test(i(s))},30:function(t,e,n){var r,o=n(9670),i=n(6048),s=n(748),c=n(3501),a=n(490),u=n(317),f=n(6200),l=f("IE_PROTO"),h=function(){},p=function(t){return"