Skip to content

Commit

Permalink
Refactore + support download from unpkg.com (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
sreichel authored Jan 13, 2025
1 parent 879702c commit a20c2f2
Show file tree
Hide file tree
Showing 14 changed files with 418 additions and 226 deletions.
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,26 @@ Helper to install via composer ...
- [jQuery](https://github.com/components/jquery)
- [TinyMCE](https://github.com/tinymce/tinymce)

<small>Note: composer install is broken since ChartJs and flatpickr. Until its fixed we try to download from https://unpkg.com</small>
## Support packages from unpkg.com

With v3 it ist possible to download files from https://unpkg.com/.

Example: add a package to composers extra section

```
"openmage-unpkg-packages": {
"@eastdesire/jscolor": {
"version": "2.5.2",
"source": "",
"target": "js/jscolor",
"files": [
"jscolor.js"
]
}
}
```

<small>Note: composer install is broken since ChartJs v3. Until its fixed we try to download from https://unpkg.com</small>

---

Expand Down
254 changes: 82 additions & 172 deletions src/OpenMage/ComposerPlugin/Copy/AbstractCopyPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,11 @@ abstract class AbstractCopyPlugin implements CopyInterface
public array $installedComposerPackages = [];

/**
* Packages installad via NPM downloadd
* Packages installad via Unpkg downloadd
*
* @var array<string, array<string, string>>
*/
public array $installedNpmPackages = [];

/**
* Package version
*/
public ?string $version = null;
public array $installedUnpkgPackages = [];

/**
* Composer event
Expand All @@ -59,101 +54,112 @@ public function __construct(Event $event)
*/
public function processComposerInstall(): void
{
$copySourcePath = null;
if ($this instanceof CopyFromComposerInterface) {
$package = $this->getComposerPackage();
if (!$package) {
return;
}
$copySourcePath = $this->getCopySourcePath();
if (!$this instanceof CopyFromComposerInterface) {
return;
}

$package = $this->getComposerPackage();
if (!$package) {
return;
}

$copySourcePath = sprintf(
'%s/%s/%s',
$this->getVendorDirectoryFromComposer(),
$this->getComposerName(),
$this->getComposerSource(),
);

$filesystem = new Filesystem();

if ($this instanceof CopyFromNpmInterface && (!$copySourcePath || !$filesystem->exists($copySourcePath))) {
if (!$filesystem->exists($copySourcePath) && $this instanceof CopyFromUnpkgInterface) {
if ($this->event->getIO()->isVerbose()) {
$this->event->getIO()->write(sprintf('Fallback to NPM for %s', $this->getNpmPackageName()));
$this->event->getIO()->write(sprintf(
'Fallback to Unpkg %s for %s',
$this->getUnpkgName(),
$this->getComposerName(),
));
}
$this->processNpmInstall();
$this->processUnpkgInstall();
return;
}

if ($copySourcePath && $this instanceof CopyFromComposerInterface) {
$finder = Finder::create()
->files()
->in($copySourcePath)
->name($this->getFilesByName());
$finder = Finder::create()
->files()
->in($copySourcePath)
->name($this->getComposerFiles());

foreach ($finder as $file) {
$copySource = $file->getPathname();
$copytarget = $this->getCopyTargetPath() . '/' . $file->getRelativePathname();
foreach ($finder as $file) {
$copySource = $file->getPathname();
$copytarget = $this->getCopyTargetPath() . '/' . $file->getRelativePathname();

try {
$filesystem->copy($copySource, $copytarget);
if ($this->event->getIO()->isVeryVerbose()) {
$this->event->getIO()->write(sprintf('Copy %s to %s', $copySource, $copytarget));
}
} catch (IOException $IOException) {
$this->event->getIO()->write($IOException->getMessage());
try {
$filesystem->copy($copySource, $copytarget);
if ($this->event->getIO()->isVeryVerbose()) {
$this->event->getIO()->write(sprintf('Copy %s to %s', $copySource, $copytarget));
}
} catch (IOException $IOException) {
$this->event->getIO()->write($IOException->getMessage());
}
}
}

/**
* Copy files as defined in NPM copy-plugin
* Copy files as defined in Unpkg copy-plugin
*/
public function processNpmInstall(): void
public function processUnpkgInstall(): void
{
if ($this instanceof CopyFromNpmInterface) {
if (!$this->getVersion()) {
return;
}
if (!$this instanceof CopyFromUnpkgInterface) {
return;
}

if (!$this->getUnpkgVersion()) {
return;
}

$sourcePath = $this->getNpmFilePath();
$sourcePath = $this->getUnpkSourcePath();

if ($this->event->getIO()->isVerbose()) {
$this->event->getIO()->write(sprintf(
'Trying to download %s %s from %s',
$this->getNpmPackageName(),
$this->getVersion(),
$sourcePath,
));
}
if ($this->event->getIO()->isVerbose()) {
$this->event->getIO()->write(sprintf(
'Trying to download %s %s from %s',
$this->getUnpkgName(),
$this->getUnpkgVersion(),
$sourcePath,
));
}

foreach ($this->getNpmPackageFiles() as $fileName) {
$sourceFilePath = $sourcePath . $fileName;
try {
$content = file_get_contents($sourceFilePath);
} catch (\ErrorException $errorException) {
$this->event->getIO()->write($errorException->getMessage());
return;
}
foreach ($this->getUnpkgFiles() as $fileName) {
$sourceFilePath = $sourcePath . $fileName;
try {
$content = file_get_contents($sourceFilePath);
} catch (\ErrorException $errorException) {
$this->event->getIO()->write($errorException->getMessage());
return;
}

if (!$content) {
$this->event->getIO()->write(sprintf('Could not read from %s', $sourceFilePath));
return;
}
if (!$content) {
$this->event->getIO()->write(sprintf('Could not read from %s', $sourceFilePath));
return;
}

try {
$filesystem = new Filesystem();
$targetFilePath = $this->getCopyTargetPath() . '/' . $fileName;
$filesystem->dumpFile($targetFilePath, $content);
if ($this->event->getIO()->isVerbose()) {
$this->event->getIO()->write(sprintf('Added %s', $fileName));
}
} catch (IOException $IOException) {
$this->event->getIO()->write($IOException->getMessage());
return;
try {
$filesystem = new Filesystem();
$targetFilePath = $this->getCopyTargetPath() . '/' . $fileName;
$filesystem->dumpFile($targetFilePath, $content);
if ($this->event->getIO()->isVerbose()) {
$this->event->getIO()->write(sprintf('Added %s', $targetFilePath));
}
} catch (IOException $IOException) {
$this->event->getIO()->write($IOException->getMessage());
return;
}
}
}

public function getComposerPackage(): ?BasePackage
{
if ($this instanceof CopyFromComposerInterface) {
$vendorName = $this->getComposerPackageName();
$vendorName = $this->getComposerName();
$module = $this->getInstalledComposerPackage($vendorName);
if ($module) {
return $module;
Expand All @@ -175,87 +181,20 @@ public function getComposerPackage(): ?BasePackage
return null;
}

/**
* @return array<string, string>|null
*/
public function getNpmPackage(): ?array
{
if ($this instanceof CopyFromNpmInterface) {
$vendorName = $this->getNpmPackageName();

$locker = $this->event->getComposer()->getLocker();
$repo = $locker->getLockedRepository();

$packages = $repo->getPackages();
$packages[] = $this->event->getComposer()->getPackage();

foreach ($packages as $package) {
/** @var array<string, string|array<string>> $extra */
$extra = $package->getExtra();

if (!isset($extra[self::EXTRA_NPM_PACKAGES][$vendorName])) {
continue;
}

$packageData = $extra[self::EXTRA_NPM_PACKAGES][$vendorName];

if (!is_array($packageData)) {
throw new Exception(sprintf('Configuration is invalid for %s', $vendorName));
}

if (array_key_exists('version', $packageData) && is_string($packageData['version'])) {
$this->setInstalledNpmPackage($vendorName, $packageData);
if ($this->event->getIO()->isVerbose()) {
$this->event->getIO()->write(sprintf(
'%s found with version %s',
$vendorName,
$packageData['version'],
));
}
return $this->getInstalledNpmPackage($vendorName);
}
}
}
return null;
}

/**
* Get path to NPM dist
*/
protected function getNpmFilePath(): string
protected function getUnpkSourcePath(): string
{
if ($this instanceof CopyFromNpmInterface) {
if ($this instanceof CopyFromUnpkgInterface) {
$search = ['{{package}}', '{{version}}'];
$replace = [$this->getNpmPackageName(), $this->getVersion()];
return str_replace($search, $replace, CopyFromNpmInterface::NPM_FALLBACK_URL);
$replace = [$this->getUnpkgName(), $this->getUnpkgVersion()];
$path = str_replace($search, $replace, CopyFromUnpkgInterface::UNPKG_URL);
return $path . ($this->getUnpkgSource() ? $this->getUnpkgSource() . '/' : '');
}
return '';
}

/**
* Get package version
*/
private function getVersion(): string
{
if (is_null($this->version)) {
$version = '';
switch (true) {
case $this instanceof CopyFromComposerInterface:
$package = $this->getComposerPackage();
$version = $package ? $package->getPrettyVersion() : '';
break;
case $this instanceof CopyFromNpmInterface:
$package = $this->getNpmPackage();
$version = $package ? $package['version'] : '';
break;
}

$this->version = ltrim($version, 'v');
}

return $this->version;
}

/**
* Get current working directory
*/
Expand Down Expand Up @@ -294,20 +233,7 @@ protected function getMageRootDirectoryFromComposer(): string
return $magentoRootDir;
}

protected function getCopySourcePath(): string
{
if ($this instanceof CopyFromComposerInterface) {
return sprintf(
'%s/%s/%s',
$this->getVendorDirectoryFromComposer(),
$this->getComposerPackageName(),
$this->getCopySource(),
);
}
return '';
}

protected function getCopyTargetPath(): string
private function getCopyTargetPath(): string
{
return sprintf(
'%s/%s%s',
Expand All @@ -326,20 +252,4 @@ private function setInstalledComposerPackage(string $vendorName, BasePackage $pa
{
$this->installedComposerPackages[$vendorName] = $package;
}

/**
* @return array<string, string>|null
*/
protected function getInstalledNpmPackage(string $vendorName): ?array
{
return $this->installedNpmPackages[$vendorName] ?? null;
}

/**
* @param array<string, string> $package
*/
private function setInstalledNpmPackage(string $vendorName, array $package): void
{
$this->installedNpmPackages[$vendorName] = $package;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,12 @@ interface CopyFromComposerInterface
/**
* Npm name
*/
public function getComposerPackageName(): string;
public function getComposerName(): string;

public function getCopySource(): string;
public function getComposerSource(): string;

/**
* @return string[]
*/
public function getFilesByName(): array;

public function processComposerInstall(): void;
public function getComposerFiles(): array;
}
Loading

0 comments on commit a20c2f2

Please sign in to comment.