Skip to content

Commit

Permalink
Install package can auto add deps to package.json #1058
Browse files Browse the repository at this point in the history
  • Loading branch information
asika32764 committed Nov 6, 2023
1 parent 71b046d commit 4b9c098
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 99 deletions.
3 changes: 2 additions & 1 deletion assets/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,6 @@
"vendors": [
"@windwalker-io/core"
]
}
},
"dependencies": {}
}
62 changes: 48 additions & 14 deletions assets/core/src/install-vendors.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { loadJson } from './utils.mjs';
import path from 'path';
import fs from 'fs';

export async function installVendors(npmVendors, composerVendors = [], to = 'www/assets/vendor') {
export async function installVendors(npmVendors = [], composerVendors = [], to = 'www/assets/vendor') {
const root = to;
let vendors = npmVendors;
const action = process.env.INSTALL_VENDOR === 'hard' ? 'Copy' : 'Link';
Expand All @@ -25,7 +25,13 @@ export async function installVendors(npmVendors, composerVendors = [], to = 'www
deleteExists(dir);
});

vendors = findVendors(composerVendors).concat(vendors);
const composerJsons = getInstalledComposerVendors(composerVendors)
.map((cv) => `vendor/${cv}/composer.json`)
.map((file) => loadJson(file))
.filter((composerJson) => composerJson?.extra?.windwalker != null);

// Install npm vendors
vendors = findNpmVendors(composerJsons).concat(vendors);
vendors = [...new Set(vendors)];

vendors.forEach((vendor) => {
Expand All @@ -35,13 +41,27 @@ export async function installVendors(npmVendors, composerVendors = [], to = 'www
}
});

composerVendors.forEach((vendor) => {
if (fs.existsSync(`vendor/${vendor}/assets`)) {
console.log(`[${action} Composer] vendor/${vendor}/assets => ${root}/${vendor}/`);
doInstall(`vendor/${vendor}/assets/`, `${root}/${vendor}/`);
// Install composer packages assets
composerJsons.forEach((composerJson) => {
const vendorName = composerJson.name;

let assets = composerJson?.extra?.windwalker?.assets?.link;

if (!assets) {
return;
}

if (!assets.endsWith('/')) {
assets += '/';
}

if (fs.existsSync(`vendor/${vendorName}/${assets}`)) {
console.log(`[${action} Composer] vendor/${vendorName}/${assets} => ${root}/${vendorName}/`);
doInstall(`vendor/${vendorName}/${assets}`, `${root}/${vendorName}/`);
}
});

// Install local saved vendors
console.log(`[${action} Local] resources/assets/vendor/**/* => ${root}/`);
doInstall('resources/assets/vendor/*', `${root}/`);
}
Expand All @@ -54,9 +74,8 @@ function doInstall(source, dest) {
}
}

function findVendors(composerVendors = []) {
function findNpmVendors(composerJsons = []) {
const pkg = path.resolve(process.cwd(), 'package.json');

const pkgJson = loadJson(pkg);

let vendors = Object.keys(pkgJson.devDependencies || {})
Expand All @@ -67,14 +86,29 @@ function findVendors(composerVendors = []) {
.map(pkgJson => pkgJson?.windwalker.vendors || [])
.flat();

composerVendors.forEach((cv) => {
const composerManifest = `vendor/${cv}/composer.json`;
const composerJson = loadJson(composerManifest);
const vendorsFromComposer = composerJsons
.map((composerJson) => composerJson?.extra?.windwalker?.assets?.vendors || {})
.map((vendors) => Object.keys(vendors))
.flat();

vendors = vendors.concat(composerJson?.windwalker?.asset_vendors || []);
});
return [ ...new Set(vendors.concat(vendorsFromComposer)) ];
}

function injectNpmPackages(composerVendors = []) {

}

return [ ...new Set(vendors) ];
function getInstalledComposerVendors(composerVendors = []) {
const composerFile = path.resolve(process.cwd(), 'composer.json');
const composerJson = loadJson(composerFile);

return [
...new Set(
Object.keys(composerJson['require'] || {})
.concat(Object.keys(composerJson['require-dev'] || {}))
.concat(composerVendors)
)
];
}

function deleteExists(dir) {
Expand Down
1 change: 0 additions & 1 deletion assets/fusion/src/utilities/webpack.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* @license __LICENSE__
*/

import { EsbuildPlugin } from 'esbuild-loader';
import { babelBasicOptions } from './babel.js';
import webpack from 'webpack';

Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
"windwalker/filesystem": "^4.0",
"windwalker/filter": "^4.0",
"windwalker/http": "^4.0",
"windwalker/test": "^4.0"
"windwalker/test": "^4.0",
"composer/semver": "^3.4"
},
"require-dev": {
"nunomaduro/collision": "^7.8"
Expand Down
1 change: 1 addition & 0 deletions resources/registry/commands.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
'schedule:install' => \Windwalker\Core\Schedule\Command\ScheduleInstallCommand::class,
'schedule:uninstall' => \Windwalker\Core\Schedule\Command\ScheduleUninstallCommand::class,

'asset:sync' => \Windwalker\Core\Asset\Command\AssetSyncCommand::class,
'asset:version' => \Windwalker\Core\Asset\Command\AssetVersionCommand::class,

'pkg:install' => \Windwalker\Core\Package\Command\PackageInstallCommand::class,
Expand Down
143 changes: 61 additions & 82 deletions src/Core/Asset/Command/AssetSyncCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

namespace Windwalker\Core\Asset\Command;

use Composer\Semver\Constraint\MultiConstraint;
use Composer\Semver\Intervals;
use Composer\Semver\Semver;
use Composer\Semver\VersionParser;
use JsonException;
use ReflectionAttribute;
use ReflectionClass;
Expand All @@ -16,25 +20,29 @@
use Windwalker\Console\IOInterface;
use Windwalker\Core\Application\ApplicationInterface;
use Windwalker\Core\Attributes\ViewModel;
use Windwalker\Core\Package\PackageRegistry;
use Windwalker\Filesystem\FileObject;
use Windwalker\Filesystem\Path;
use Windwalker\Utilities\Str;

use function Windwalker\fs;

/**
* The AssetSyncCommand class.
*
* @deprecated No use now.
*/
#[CommandWrapper(description: 'Asset sync helpers', hidden: true)]
#[CommandWrapper(description: 'Sync vendor assets dependencies to package.json', hidden: true)]
class AssetSyncCommand implements CommandInterface
{
/**
* AssetSyncCommand constructor.
*
* @param ApplicationInterface $app
* @param PackageRegistry $packageRegistry
*/
public function __construct(protected ApplicationInterface $app)
{
public function __construct(
protected ApplicationInterface $app,
protected PackageRegistry $packageRegistry,
) {
}

/**
Expand All @@ -46,37 +54,7 @@ public function __construct(protected ApplicationInterface $app)
*/
public function configure(Command $command): void
{
$command->addArgument(
'dir',
InputArgument::OPTIONAL,
'Where to find views.'
);
// $command->addArgument(
// 'dest',
// InputArgument::OPTIONAL,
// 'Where to copy files.'
// );
$command->addOption(
'ns',
null,
InputOption::VALUE_REQUIRED,
'The namespace start from this path.',
$this->app->config('asset.namespace_base')
);
$command->addOption(
'pretty',
null,
InputOption::VALUE_OPTIONAL,
'JSON pretty print.',
false
);
// $command->addOption(
// 'type',
// null,
// InputOption::VALUE_REQUIRED,
// 'css | js',
// 'js'
// );
//
}

/**
Expand All @@ -89,68 +67,69 @@ public function configure(Command $command): void
*/
public function execute(IOInterface $io): int
{
$dir = $io->getArgument('dir') ?? '@source/Module';
$dir = $this->app->path($dir);
$packages = $this->packageRegistry->getPackages();
$packageJsonFile = fs(WINDWALKER_ROOT . '/package.json');

// $dest = $io->getArgument('dest');
if (!$packageJsonFile->isFile()) {
throw new \RuntimeException('package.json not exists to sync.');
}

// if (!$dest) {
// throw new InvalidArgumentException('Please provide dest path.');
// }
$io->style()->title('Sync package.json Versions');

// $this->dest = $this->app->path($dest);
// $this->ns = $ns = (string) $io->getOption('ns');
// $this->type = (string) $io->getOption('type');
$packageJson = $packageJsonFile->readAndParse('json');

$map = [];
$versionParser = new VersionParser();

AttributesAccessor::scanDirAndRunAttributes(
ViewModel::class,
$dir,
(string) $io->getOption('ns'),
handler: function (ViewModel $vm, string $className, FileObject $file) use ($io, &$map) {
$this->handleAssets($vm, $className, $file, $io, $map);
},
options: ReflectionAttribute::IS_INSTANCEOF
);
$override = false;

$flags = JSON_THROW_ON_ERROR;
foreach ($packages as $package) {
$json = $package::composerJson();

if ($io->getOption('pretty') !== false) {
$flags |= JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES;
}
if (!$json) {
continue;
}

$io->writeln(json_encode($map, $flags));
$vendors = $json['extra']['windwalker']['assets']['vendors'] ?? [];

return 0;
}
foreach ($vendors as $vendor => $versions) {
$constraints = $versionParser->parseConstraints($versions);

public function handleAssets(ViewModel $vm, string $className, FileObject $file, IOInterface $io, array &$map): void
{
$dir = $file->getPath();
$ns = (string) $io->getOption('ns');
if ($currentVersions = $packageJson->getDeep('dependencies.' . $vendor)) {
$currentConstraints = $versionParser->parseConstraints($currentVersions);

$src = $dir . '/assets/**/*.{js,mjs}';
$src = Path::relative($this->app->path('@root') . '/', $src);
$dest = Path::clean(
strtolower(ltrim($vm->getModuleName() ?? $this->guessName($className, $ns), '/\\'))
) . DIRECTORY_SEPARATOR;
if (!Intervals::isSubsetOf($constraints, $currentConstraints)) {
$packageJson->setDeep(
'dependencies.' . $vendor,
$newVersion = $currentVersions . '|' . $versions
);

$map['js'][$src] = $dest;
$override = true;

foreach ($vm->css as $cssFile) {
$src = $dir . '/asset/' . $cssFile;
$src = Path::relative($this->app->path('@root') . '/', $src);
$io->writeln("Replace: <info>\"$vendor\"</info> version to \"$newVersion\"");
}
} else {
$packageJson->setDeep(
'dependencies.' . $vendor,
$versions
);

$map['css'][] = $src;
$override = true;

$io->writeln("Add: <info>\"$vendor\"</info>: \"$versions\"");
}
}
}
}

protected function guessName(string $class, string $nsBase): string
{
$ref = new ReflectionClass($class);
$ns = $ref->getNamespaceName();
if ($override) {
$packageJsonFile->write(
json_encode($packageJson, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
);

return Str::removeLeft($ns, $nsBase);
$io->writeln('package.json file modified.');
} else {
$io->writeln('package.json not changed.');
}

return 0;
}
}

0 comments on commit 4b9c098

Please sign in to comment.