From 6f54bc25c3bd643f700df71267a964ca4d78fa74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jib=C3=A9=20Barth?= Date: Tue, 21 May 2024 15:53:11 +0200 Subject: [PATCH 1/4] [AssetMapper] Allow to define entrypoint in importmap.php --- src/PackageJsonSynchronizer.php | 15 ++++++++--- .../symfony/new-package/assets/package.json | 5 ++-- tests/PackageJsonSynchronizerTest.php | 25 +++++++++++++------ 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/PackageJsonSynchronizer.php b/src/PackageJsonSynchronizer.php index 698894c5b..a3049c754 100644 --- a/src/PackageJsonSynchronizer.php +++ b/src/PackageJsonSynchronizer.php @@ -147,7 +147,7 @@ private function resolveImportMapPackages($phpPackage): array } $dependencies = []; - + $entrypoints = $packageJson->read()['symfony']['entrypoints'] ?? []; foreach ($packageJson->read()['symfony']['importmap'] ?? [] as $importMapName => $constraintConfig) { if (\is_array($constraintConfig)) { $constraint = $constraintConfig['version'] ?? []; @@ -163,6 +163,7 @@ private function resolveImportMapPackages($phpPackage): array $dependencies[$importMapName] = [ 'path' => $path, + 'entrypoint' => \in_array($importMapName, $entrypoints, true), ]; continue; @@ -239,7 +240,7 @@ private function shouldUpdateConstraint(string $existingConstraint, string $cons } /** - * @param array $importMapEntries + * @param array $importMapEntries */ private function updateImportMap(array $importMapEntries): void { @@ -267,8 +268,14 @@ private function updateImportMap(array $importMapEntries): void $this->io->writeError(sprintf('Updating package %s from %s to %s.', $name, $version, $versionConstraint)); } + $arguments = []; + if (isset($importMapEntry['entrypoint']) && $importMapEntry['entrypoint'] === true) { + $arguments[] = '--entrypoint'; + } + if (isset($importMapEntry['path'])) { - $arguments = [$name, '--path='.$importMapEntry['path']]; + $arguments[] = $name; + $arguments[] = '--path='.$importMapEntry['path']; $this->scriptExecutor->execute( 'symfony-cmd', 'importmap:require', @@ -283,7 +290,7 @@ private function updateImportMap(array $importMapEntries): void if ($importMapEntry['package'] !== $name) { $packageName .= '='.$name; } - $arguments = [$packageName]; + $arguments[] = $packageName; $this->scriptExecutor->execute( 'symfony-cmd', 'importmap:require', diff --git a/tests/Fixtures/packageJson/vendor/symfony/new-package/assets/package.json b/tests/Fixtures/packageJson/vendor/symfony/new-package/assets/package.json index e4003ea6c..b67245910 100644 --- a/tests/Fixtures/packageJson/vendor/symfony/new-package/assets/package.json +++ b/tests/Fixtures/packageJson/vendor/symfony/new-package/assets/package.json @@ -9,12 +9,13 @@ } } }, - "entrypoints": ["admin.js"], + "entrypoints": ["admin.js", "@symfony/new-package/entry.js"], "importmap": { "@hotcake/foo": "^1.9.0", "@symfony/new-package": { "version": "path:%PACKAGE%/dist/loader.js" - } + }, + "@symfony/new-package/entry.js": "path:%PACKAGE%/entry.js" } }, "peerDependencies": { diff --git a/tests/PackageJsonSynchronizerTest.php b/tests/PackageJsonSynchronizerTest.php index 7e6b27c0d..e1f047f6f 100644 --- a/tests/PackageJsonSynchronizerTest.php +++ b/tests/PackageJsonSynchronizerTest.php @@ -189,7 +189,7 @@ public function testSynchronizeNewPackage() ], ], ], - 'entrypoints' => ['admin.js'], + 'entrypoints' => ['admin.js', '@symfony/new-package/entry.js'], ], json_decode(file_get_contents($this->tempDir.'/assets/controllers.json'), true) ); @@ -323,11 +323,14 @@ public function testSynchronizeAssetMapperNewPackage() file_put_contents($this->tempDir.'/importmap.php', 'tempDir.'/vendor/symfony/new-package/assets/dist/loader.js'; - $this->scriptExecutor->expects($this->exactly(2)) + $entrypointPath = $this->tempDir.'/vendor/symfony/new-package/assets/entry.js'; + + $this->scriptExecutor->expects($this->exactly(3)) ->method('execute') ->withConsecutive( ['symfony-cmd', 'importmap:require', ['@hotcake/foo@^1.9.0']], - ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]] + ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]], + ['symfony-cmd', 'importmap:require', ['--entrypoint','@symfony/new-package/entry.js', '--path='.$entrypointPath]] ); $this->synchronizer->synchronize([ @@ -382,7 +385,7 @@ public function testSynchronizeAssetMapperNewPackage() ], ], ], - 'entrypoints' => ['admin.js'], + 'entrypoints' => ['admin.js', '@symfony/new-package/entry.js'], ], json_decode(file_get_contents($this->tempDir.'/assets/controllers.json'), true) ); @@ -399,11 +402,14 @@ public function testSynchronizeAssetMapperUpgradesPackageIfNeeded() file_put_contents($this->tempDir.'/importmap.php', sprintf('tempDir.'/vendor/symfony/new-package/assets/dist/loader.js'; - $this->scriptExecutor->expects($this->exactly(2)) + $entrypointPath = $this->tempDir.'/vendor/symfony/new-package/assets/entry.js'; + + $this->scriptExecutor->expects($this->exactly(3)) ->method('execute') ->withConsecutive( ['symfony-cmd', 'importmap:require', ['@hotcake/foo@^1.9.0']], - ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]] + ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]], + ['symfony-cmd', 'importmap:require', ['--entrypoint','@symfony/new-package/entry.js', '--path='.$entrypointPath]] ); $this->synchronizer->synchronize([ @@ -425,10 +431,13 @@ public function testSynchronizeAssetMapperSkipsUpgradeIfAlreadySatisfied() file_put_contents($this->tempDir.'/importmap.php', sprintf('tempDir.'/vendor/symfony/new-package/assets/dist/loader.js'; - $this->scriptExecutor->expects($this->once()) + $entrypointPath = $this->tempDir.'/vendor/symfony/new-package/assets/entry.js'; + + $this->scriptExecutor->expects($this->exactly(2)) ->method('execute') ->withConsecutive( - ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]] + ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]], + ['symfony-cmd', 'importmap:require', ['--entrypoint','@symfony/new-package/entry.js', '--path='.$entrypointPath]] ); $this->synchronizer->synchronize([ From 14189260e2513403467d8897604ae85578713219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jib=C3=A9=20Barth?= Date: Tue, 21 May 2024 16:00:08 +0200 Subject: [PATCH 2/4] Apply fabbot patch --- src/PackageJsonSynchronizer.php | 2 +- tests/PackageJsonSynchronizerTest.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/PackageJsonSynchronizer.php b/src/PackageJsonSynchronizer.php index a3049c754..23594e840 100644 --- a/src/PackageJsonSynchronizer.php +++ b/src/PackageJsonSynchronizer.php @@ -269,7 +269,7 @@ private function updateImportMap(array $importMapEntries): void } $arguments = []; - if (isset($importMapEntry['entrypoint']) && $importMapEntry['entrypoint'] === true) { + if (isset($importMapEntry['entrypoint']) && true === $importMapEntry['entrypoint']) { $arguments[] = '--entrypoint'; } diff --git a/tests/PackageJsonSynchronizerTest.php b/tests/PackageJsonSynchronizerTest.php index e1f047f6f..ad5b32e3c 100644 --- a/tests/PackageJsonSynchronizerTest.php +++ b/tests/PackageJsonSynchronizerTest.php @@ -330,7 +330,7 @@ public function testSynchronizeAssetMapperNewPackage() ->withConsecutive( ['symfony-cmd', 'importmap:require', ['@hotcake/foo@^1.9.0']], ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]], - ['symfony-cmd', 'importmap:require', ['--entrypoint','@symfony/new-package/entry.js', '--path='.$entrypointPath]] + ['symfony-cmd', 'importmap:require', ['--entrypoint', '@symfony/new-package/entry.js', '--path='.$entrypointPath]] ); $this->synchronizer->synchronize([ @@ -409,7 +409,7 @@ public function testSynchronizeAssetMapperUpgradesPackageIfNeeded() ->withConsecutive( ['symfony-cmd', 'importmap:require', ['@hotcake/foo@^1.9.0']], ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]], - ['symfony-cmd', 'importmap:require', ['--entrypoint','@symfony/new-package/entry.js', '--path='.$entrypointPath]] + ['symfony-cmd', 'importmap:require', ['--entrypoint', '@symfony/new-package/entry.js', '--path='.$entrypointPath]] ); $this->synchronizer->synchronize([ @@ -437,7 +437,7 @@ public function testSynchronizeAssetMapperSkipsUpgradeIfAlreadySatisfied() ->method('execute') ->withConsecutive( ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]], - ['symfony-cmd', 'importmap:require', ['--entrypoint','@symfony/new-package/entry.js', '--path='.$entrypointPath]] + ['symfony-cmd', 'importmap:require', ['--entrypoint', '@symfony/new-package/entry.js', '--path='.$entrypointPath]] ); $this->synchronizer->synchronize([ From b7b72e2e80e7740538ae464e7c670bf74bb804c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jib=C3=A9=20Barth?= Date: Sun, 2 Feb 2025 13:43:55 +0100 Subject: [PATCH 3/4] Use new key/keword instead use $.symfony.entrypoints in package.json Now, it allow "@mybundle/script.js": "entrypoint:%PACKAGE%/script.js" or "@mybundle/script.js": {"version": "entrypoint:%PACKAGE%/script.js"} or "@mybundle/script.js": {"version": "path:%PACKAGE%/script.js", "entrypoint": true} --- src/PackageJsonSynchronizer.php | 30 ++++++++++++------- .../symfony/new-package/assets/package.json | 8 +++-- tests/PackageJsonSynchronizerTest.php | 22 +++++++++----- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/PackageJsonSynchronizer.php b/src/PackageJsonSynchronizer.php index 23594e840..5c45fc320 100644 --- a/src/PackageJsonSynchronizer.php +++ b/src/PackageJsonSynchronizer.php @@ -147,14 +147,24 @@ private function resolveImportMapPackages($phpPackage): array } $dependencies = []; - $entrypoints = $packageJson->read()['symfony']['entrypoints'] ?? []; foreach ($packageJson->read()['symfony']['importmap'] ?? [] as $importMapName => $constraintConfig) { - if (\is_array($constraintConfig)) { - $constraint = $constraintConfig['version'] ?? []; - $package = $constraintConfig['package'] ?? $importMapName; - } else { + if (\is_string($constraintConfig)) { + // Case "jquery": "^3.0" | "@mybundle/script.js": "path:%PACKAGE%/script.js" $constraint = $constraintConfig; $package = $importMapName; + $entrypoint = false; + } else { + // Case "jquery": {"version": "^3.0"} | "@mybundle/script.js": {"version": "path:%PACKAGE%/script.js", "entrypoint": true} + // Note that non-path assets can't be entrypoint + $constraint = $constraintConfig['version'] ?? ''; + $package = $constraintConfig['package'] ?? $importMapName; + $entrypoint = $constraintConfig['entrypoint'] ?? false; + } + + // Case "@mybundle/script.js": "entrypoint:%PACKAGE%/script.js" | "@mybundle/script.js": {"version": "entrypoint:%PACKAGE%/script.js"} + if (0 === strpos($constraint, 'entrypoint:')) { + $entrypoint = true; + $constraint = str_replace('entrypoint:', 'path:', $constraint); } if (0 === strpos($constraint, 'path:')) { @@ -163,7 +173,7 @@ private function resolveImportMapPackages($phpPackage): array $dependencies[$importMapName] = [ 'path' => $path, - 'entrypoint' => \in_array($importMapName, $entrypoints, true), + 'entrypoint' => $entrypoint, ]; continue; @@ -269,11 +279,11 @@ private function updateImportMap(array $importMapEntries): void } $arguments = []; - if (isset($importMapEntry['entrypoint']) && true === $importMapEntry['entrypoint']) { - $arguments[] = '--entrypoint'; - } - if (isset($importMapEntry['path'])) { + if (isset($importMapEntry['entrypoint']) && true === $importMapEntry['entrypoint']) { + $arguments[] = '--entrypoint'; + } + $arguments[] = $name; $arguments[] = '--path='.$importMapEntry['path']; $this->scriptExecutor->execute( diff --git a/tests/Fixtures/packageJson/vendor/symfony/new-package/assets/package.json b/tests/Fixtures/packageJson/vendor/symfony/new-package/assets/package.json index b67245910..419528379 100644 --- a/tests/Fixtures/packageJson/vendor/symfony/new-package/assets/package.json +++ b/tests/Fixtures/packageJson/vendor/symfony/new-package/assets/package.json @@ -9,13 +9,17 @@ } } }, - "entrypoints": ["admin.js", "@symfony/new-package/entry.js"], + "entrypoints": ["admin.js"], "importmap": { "@hotcake/foo": "^1.9.0", "@symfony/new-package": { "version": "path:%PACKAGE%/dist/loader.js" }, - "@symfony/new-package/entry.js": "path:%PACKAGE%/entry.js" + "@symfony/new-package/entry.js": "entrypoint:%PACKAGE%/entry.js", + "@symfony/new-package/entry2.js": { + "version": "path:%PACKAGE%/entry2.js", + "entrypoint": true + } } }, "peerDependencies": { diff --git a/tests/PackageJsonSynchronizerTest.php b/tests/PackageJsonSynchronizerTest.php index ad5b32e3c..2af68073f 100644 --- a/tests/PackageJsonSynchronizerTest.php +++ b/tests/PackageJsonSynchronizerTest.php @@ -189,7 +189,7 @@ public function testSynchronizeNewPackage() ], ], ], - 'entrypoints' => ['admin.js', '@symfony/new-package/entry.js'], + 'entrypoints' => ['admin.js'], ], json_decode(file_get_contents($this->tempDir.'/assets/controllers.json'), true) ); @@ -324,13 +324,15 @@ public function testSynchronizeAssetMapperNewPackage() $fileModulePath = $this->tempDir.'/vendor/symfony/new-package/assets/dist/loader.js'; $entrypointPath = $this->tempDir.'/vendor/symfony/new-package/assets/entry.js'; + $secondEntrypointPath = $this->tempDir.'/vendor/symfony/new-package/assets/entry2.js'; - $this->scriptExecutor->expects($this->exactly(3)) + $this->scriptExecutor->expects($this->exactly(4)) ->method('execute') ->withConsecutive( ['symfony-cmd', 'importmap:require', ['@hotcake/foo@^1.9.0']], ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]], - ['symfony-cmd', 'importmap:require', ['--entrypoint', '@symfony/new-package/entry.js', '--path='.$entrypointPath]] + ['symfony-cmd', 'importmap:require', ['--entrypoint', '@symfony/new-package/entry.js', '--path='.$entrypointPath]], + ['symfony-cmd', 'importmap:require', ['--entrypoint', '@symfony/new-package/entry2.js', '--path='.$secondEntrypointPath]] ); $this->synchronizer->synchronize([ @@ -385,7 +387,7 @@ public function testSynchronizeAssetMapperNewPackage() ], ], ], - 'entrypoints' => ['admin.js', '@symfony/new-package/entry.js'], + 'entrypoints' => ['admin.js'], ], json_decode(file_get_contents($this->tempDir.'/assets/controllers.json'), true) ); @@ -403,13 +405,15 @@ public function testSynchronizeAssetMapperUpgradesPackageIfNeeded() $fileModulePath = $this->tempDir.'/vendor/symfony/new-package/assets/dist/loader.js'; $entrypointPath = $this->tempDir.'/vendor/symfony/new-package/assets/entry.js'; + $secondEntrypointPath = $this->tempDir.'/vendor/symfony/new-package/assets/entry2.js'; - $this->scriptExecutor->expects($this->exactly(3)) + $this->scriptExecutor->expects($this->exactly(4)) ->method('execute') ->withConsecutive( ['symfony-cmd', 'importmap:require', ['@hotcake/foo@^1.9.0']], ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]], - ['symfony-cmd', 'importmap:require', ['--entrypoint', '@symfony/new-package/entry.js', '--path='.$entrypointPath]] + ['symfony-cmd', 'importmap:require', ['--entrypoint', '@symfony/new-package/entry.js', '--path='.$entrypointPath]], + ['symfony-cmd', 'importmap:require', ['--entrypoint', '@symfony/new-package/entry2.js', '--path='.$secondEntrypointPath]] ); $this->synchronizer->synchronize([ @@ -427,6 +431,10 @@ public function testSynchronizeAssetMapperSkipsUpgradeIfAlreadySatisfied() // constraint in package.json is ^1.9.0 'version' => '1.9.1', ], + '@symfony/new-package/entry2.js' => [ + 'path' => './vendor/symfony/new-package/assets/entry2.js', + 'entrypoint' => true, + ] ]; file_put_contents($this->tempDir.'/importmap.php', sprintf('method('execute') ->withConsecutive( ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]], - ['symfony-cmd', 'importmap:require', ['--entrypoint', '@symfony/new-package/entry.js', '--path='.$entrypointPath]] + ['symfony-cmd', 'importmap:require', ['--entrypoint', '@symfony/new-package/entry.js', '--path='.$entrypointPath]], ); $this->synchronizer->synchronize([ From 20f3f73cfd89f5778b216165932f5c6d3fa3ef5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jib=C3=A9=20Barth?= Date: Sun, 2 Feb 2025 14:05:54 +0100 Subject: [PATCH 4/4] =?UTF-8?q?Self=20review=20=F0=9F=A4=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/PackageJsonSynchronizer.php | 7 +++---- tests/PackageJsonSynchronizerTest.php | 10 +++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/PackageJsonSynchronizer.php b/src/PackageJsonSynchronizer.php index 5c45fc320..74ec41e11 100644 --- a/src/PackageJsonSynchronizer.php +++ b/src/PackageJsonSynchronizer.php @@ -147,6 +147,7 @@ private function resolveImportMapPackages($phpPackage): array } $dependencies = []; + foreach ($packageJson->read()['symfony']['importmap'] ?? [] as $importMapName => $constraintConfig) { if (\is_string($constraintConfig)) { // Case "jquery": "^3.0" | "@mybundle/script.js": "path:%PACKAGE%/script.js" @@ -278,14 +279,12 @@ private function updateImportMap(array $importMapEntries): void $this->io->writeError(sprintf('Updating package %s from %s to %s.', $name, $version, $versionConstraint)); } - $arguments = []; if (isset($importMapEntry['path'])) { + $arguments = [$name, '--path='.$importMapEntry['path']]; if (isset($importMapEntry['entrypoint']) && true === $importMapEntry['entrypoint']) { $arguments[] = '--entrypoint'; } - $arguments[] = $name; - $arguments[] = '--path='.$importMapEntry['path']; $this->scriptExecutor->execute( 'symfony-cmd', 'importmap:require', @@ -300,7 +299,7 @@ private function updateImportMap(array $importMapEntries): void if ($importMapEntry['package'] !== $name) { $packageName .= '='.$name; } - $arguments[] = $packageName; + $arguments = [$packageName]; $this->scriptExecutor->execute( 'symfony-cmd', 'importmap:require', diff --git a/tests/PackageJsonSynchronizerTest.php b/tests/PackageJsonSynchronizerTest.php index 2af68073f..98a750d6d 100644 --- a/tests/PackageJsonSynchronizerTest.php +++ b/tests/PackageJsonSynchronizerTest.php @@ -331,8 +331,8 @@ public function testSynchronizeAssetMapperNewPackage() ->withConsecutive( ['symfony-cmd', 'importmap:require', ['@hotcake/foo@^1.9.0']], ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]], - ['symfony-cmd', 'importmap:require', ['--entrypoint', '@symfony/new-package/entry.js', '--path='.$entrypointPath]], - ['symfony-cmd', 'importmap:require', ['--entrypoint', '@symfony/new-package/entry2.js', '--path='.$secondEntrypointPath]] + ['symfony-cmd', 'importmap:require', ['@symfony/new-package/entry.js', '--path='.$entrypointPath, '--entrypoint']], + ['symfony-cmd', 'importmap:require', ['@symfony/new-package/entry2.js', '--path='.$secondEntrypointPath, '--entrypoint']], ); $this->synchronizer->synchronize([ @@ -412,8 +412,8 @@ public function testSynchronizeAssetMapperUpgradesPackageIfNeeded() ->withConsecutive( ['symfony-cmd', 'importmap:require', ['@hotcake/foo@^1.9.0']], ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]], - ['symfony-cmd', 'importmap:require', ['--entrypoint', '@symfony/new-package/entry.js', '--path='.$entrypointPath]], - ['symfony-cmd', 'importmap:require', ['--entrypoint', '@symfony/new-package/entry2.js', '--path='.$secondEntrypointPath]] + ['symfony-cmd', 'importmap:require', ['@symfony/new-package/entry.js', '--path='.$entrypointPath, '--entrypoint']], + ['symfony-cmd', 'importmap:require', ['@symfony/new-package/entry2.js', '--path='.$secondEntrypointPath, '--entrypoint']] ); $this->synchronizer->synchronize([ @@ -445,7 +445,7 @@ public function testSynchronizeAssetMapperSkipsUpgradeIfAlreadySatisfied() ->method('execute') ->withConsecutive( ['symfony-cmd', 'importmap:require', ['@symfony/new-package', '--path='.$fileModulePath]], - ['symfony-cmd', 'importmap:require', ['--entrypoint', '@symfony/new-package/entry.js', '--path='.$entrypointPath]], + ['symfony-cmd', 'importmap:require', ['@symfony/new-package/entry.js', '--path='.$entrypointPath, '--entrypoint']], ); $this->synchronizer->synchronize([