Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Completed npm commands (npm:install, npm:update, npm:run) #1202

Merged
merged 30 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0780ac2
Added inital work on npm commands
jaxwilko Sep 12, 2024
2c6bea7
Added fix for root issued commands
jaxwilko Sep 12, 2024
05eaed4
Added npm:install command and moved scripts
jaxwilko Sep 12, 2024
cd62ba5
Added better error reporting and moved tests
jaxwilko Sep 15, 2024
9fbcc05
Added fixes for silent flag and added disable-tty as an option
jaxwilko Sep 20, 2024
8a76ea8
Added tests and fixtures
jaxwilko Sep 20, 2024
90a0d17
Renamed vitetest theme to assettest
jaxwilko Sep 23, 2024
e7e770d
Added fix to PackageJson to handle malformed json files
jaxwilko Sep 23, 2024
3d3b2bf
Added caching of package.json file and dynamic ignored loading to ena…
jaxwilko Sep 23, 2024
b5b3b97
Added simplification and support for testing to asset:install commands
jaxwilko Sep 23, 2024
d27911f
Added catch used by original command
jaxwilko Sep 23, 2024
4b53b50
Removed incorrect alias
jaxwilko Sep 23, 2024
f0dcdf7
Added fix for theme rename
jaxwilko Sep 23, 2024
8bca2d1
Added trait for preserving package.json between tests logic
jaxwilko Sep 23, 2024
9c5394c
Updated eslintignore for test theme change
jaxwilko Sep 23, 2024
914cbea
Added test fixtures
jaxwilko Sep 23, 2024
e323a97
Added tests for asset install commands
jaxwilko Sep 23, 2024
2a222bf
Removed json_validate as it's only available in php8.3
jaxwilko Sep 23, 2024
a8b119f
Updated eslintignore
jaxwilko Sep 23, 2024
5b49911
Added SystemException as base for package exceptions
jaxwilko Sep 24, 2024
dc28b28
Added corrupt test for PackageJson
jaxwilko Sep 24, 2024
54843a6
Added check for PackageManager to ensure the config file for a regist…
jaxwilko Sep 24, 2024
1969a0d
Renamed test package.json file
jaxwilko Sep 24, 2024
7c64366
Added fix for package json restoring and added test case for --packag…
jaxwilko Sep 24, 2024
76fec29
Update modules/system/console/asset/npm/NpmInstall.php
LukeTowers Sep 24, 2024
f8ff0dd
Update modules/system/console/asset/AssetInstall.php
LukeTowers Sep 24, 2024
c39bdb2
Added phpdocs
jaxwilko Oct 4, 2024
2b2ab51
Merge branch 'wip/npm-commands' of github.com:wintercms/winter into w…
jaxwilko Oct 4, 2024
4587abc
Merge branch 'develop' into wip/npm-commands
jaxwilko Oct 25, 2024
2f16357
Removed custom exceptions
jaxwilko Oct 25, 2024
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
4 changes: 3 additions & 1 deletion modules/system/.eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ assets/vendor
# Ignore test fixtures
tests/js
tests/fixtures/themes/test/assets/js
tests/fixtures/themes/vitetest/assets/javascript
tests/fixtures/themes/npmtest
tests/fixtures/themes/assettest
tests/fixtures/plugins/mix
5 changes: 3 additions & 2 deletions modules/system/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -332,8 +332,9 @@ protected function registerConsole()
$this->registerConsoleCommand('vite.list', Console\Asset\Vite\ViteList::class);
$this->registerConsoleCommand('vite.watch', Console\Asset\Vite\ViteWatch::class);

$this->registerConsoleCommand('npm.run', Console\Asset\NpmRun::class);
$this->registerConsoleCommand('npm.update', Console\Asset\NpmUpdate::class);
$this->registerConsoleCommand('npm.run', Console\Asset\Npm\NpmRun::class);
$this->registerConsoleCommand('npm.install', Console\Asset\Npm\NpmInstall::class);
$this->registerConsoleCommand('npm.update', Console\Asset\Npm\NpmUpdate::class);
}

/*
Expand Down
15 changes: 11 additions & 4 deletions modules/system/classes/asset/PackageJson.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,24 @@ class PackageJson
/**
* The contents of the package.json being modified
*/
protected array $data;
protected array $data = [];

/**
* Create a new instance with optional path, loads file if file already exists
* @throws \JsonException
*/
public function __construct(
protected ?string $path = null
) {
$this->data = File::exists($this->path)
? json_decode(File::get($this->path), JSON_OBJECT_AS_ARRAY)
: [];
if (File::exists($this->path)) {
// Test the json to insure it's valid
$json = json_decode(File::get($this->path), JSON_OBJECT_AS_ARRAY);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \JsonException('The contents of the file "' . $this->path . '" is not valid json.');
}

$this->data = $json;
}
}

/**
Expand Down
87 changes: 70 additions & 17 deletions modules/system/classes/asset/PackageManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,14 @@ class PackageManager
{
use \Winter\Storm\Support\Traits\Singleton;

public const TYPE_THEME = 'theme';
public const TYPE_MODULE = 'module';
public const TYPE_PLUGIN = 'plugin';

/**
* The filename that stores the package definition.
*/
protected string $packageJson = 'package.json';
protected PackageJson $packageJson;

/**
* @var array<string, array<string, string>> List of package types and registration methods
Expand Down Expand Up @@ -56,6 +60,8 @@ class PackageManager
*/
public function init(): void
{
$this->setPackageJsonPath(base_path('package.json'));

$packagePaths = [];

/*
Expand Down Expand Up @@ -183,12 +189,14 @@ public static function registerCallback(callable $callback): void
/**
* Calls the deferred callbacks.
*/
public function fireCallbacks(): void
public function fireCallbacks(): static
{
// Call callbacks
foreach (static::$callbacks as $callback) {
$callback($this);
}

return $this;
}

/**
Expand All @@ -206,6 +214,10 @@ public function getPackages(string $type, bool $includeIgnored = false): array
{
$packages = $this->packages[$type] ?? [];

foreach ($packages as $index => $package) {
$packages[$index]['ignored'] = $this->isPackageIgnored($package['path']);
}

ksort($packages);

if (!$includeIgnored) {
Expand All @@ -223,9 +235,13 @@ public function getPackages(string $type, bool $includeIgnored = false): array
public function hasPackage(string $name, bool $includeIgnored = false): bool
{
foreach ($this->packages ?? [] as $packages) {
foreach ($packages as $packageName => $config) {
if (($name === $packageName) && (!$config['ignored'] || $includeIgnored)) {
return true;
foreach ($packages as $packageName => $package) {
if ($name === $packageName) {
if ((!$this->isPackageIgnored($package['path']) || $includeIgnored)) {
return true;
}

return false;
}
}
}
Expand All @@ -239,10 +255,12 @@ public function hasPackage(string $name, bool $includeIgnored = false): bool
public function getPackage(string $name, bool $includeIgnored = false): array
{
$results = [];
foreach ($this->packages ?? [] as $packages) {
foreach ($packages as $packageName => $config) {
if (($name === $packageName) && (!$config['ignored'] || $includeIgnored)) {
$results[] = $config;
foreach ($this->packages ?? [] as $type => $packages) {
foreach ($packages as $packageName => $package) {
if (($name === $packageName)) {
if (!$this->isPackageIgnored($package['path']) || $includeIgnored) {
$results[] = $package + ['type' => $type];
}
}
}
}
Expand Down Expand Up @@ -297,6 +315,17 @@ public function registerPackage(string $name, string $path, string $type = 'mix'
));
}

$package = $path . '/package.json';
$config = $path . DIRECTORY_SEPARATOR . $configFile;

if (!File::exists($config)) {
throw new SystemException(sprintf(
'Cannot register "%s" as a compilable package; the config file "%s" does not exist.',
$name,
$config
));
}

// Check for any existing packages already registered under the provided name
if (isset($this->packages[$name])) {
throw new SystemException(sprintf(
Expand All @@ -306,9 +335,6 @@ public function registerPackage(string $name, string $path, string $type = 'mix'
));
}

$package = "$path/{$this->packageJson}";
$config = $path . DIRECTORY_SEPARATOR . $configFile;

// Check for any existing package that already registers the given compilable config path
foreach ($this->packages[$type] ?? [] as $packageName => $settings) {
if ($settings['config'] === $config) {
Expand All @@ -325,11 +351,40 @@ public function registerPackage(string $name, string $path, string $type = 'mix'
$this->packages[$type][$name] = [
'path' => $path,
'package' => $package,
'config' => $config,
'ignored' => $this->isPackageIgnored($path),
'config' => $config
];
}

public function getPackageTypeFromName(string $package): ?string
{
// Check if package could be a module
if (Str::startsWith($package, 'module-') && !in_array($package, ['system', 'backend', 'cms'])) {
return static::TYPE_MODULE;
}

// Check if package could be a theme
if (
in_array('Cms', Config::get('cms.loadModules'))
&& Str::startsWith($package, 'theme-')
&& Theme::exists(Str::after($package, 'theme-'))
) {
return static::TYPE_THEME;
}

// Check if a package could be a plugin
if (PluginManager::instance()->exists($package)) {
return static::TYPE_PLUGIN;
}

return null;
}

public function setPackageJsonPath(string $packageJsonPath): static
{
$this->packageJson = new PackageJson($packageJsonPath);
return $this;
}

/**
* Returns the registration method for a compiler type
*/
Expand All @@ -343,8 +398,6 @@ protected function getRegistrationMethod(string $type): string
*/
protected function isPackageIgnored(string $packagePath): bool
{
// Load the main package.json for the project
$packageJson = new PackageJson(base_path($this->packageJson));
return $packageJson->hasIgnoredPackage($packagePath);
return $this->packageJson->hasIgnoredPackage($packagePath);
}
}
Loading
Loading