Skip to content

Commit

Permalink
feat(cli): add flags to handle native deps (#2567)
Browse files Browse the repository at this point in the history
This change introduces two new flags to the CLI to handle transitive
dependencies on packages containing native modules.
`--allow-native-package [package-name...]` to selectively allow native
packages when exporting a dynamic plugin and allowing it's installation
into the exported dynamic plugin and `--suppress-native-package
[package-name..]` which replaces the native package with an empty
package during export, preventing the native package's inclusion into
the exported dynamic plugin's private dependencies.

Signed-off-by: Stan Lewis <[email protected]>
  • Loading branch information
gashcrumb authored and schultzp2020 committed Nov 27, 2024
1 parent aa9b240 commit abd9dec
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 9 deletions.
9 changes: 9 additions & 0 deletions .changeset/long-pants-allow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@janus-idp/cli": patch
---

This change adds two new flags to handle native module dependencies.

- `--allow-native-package [package-name...]`: flag to selectively allow native packages when exporting a dynamic plugin and allowing it's installation into the exported dynamic plugin.

- `--suppress-native-package [package-name..]`: flag which replaces the native package with an empty package during export, preventing the native package's inclusion into the exported dynamic plugin's private dependencies.
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ export async function backend(opts: OptionValues): Promise<string> {
);
}

const derivedPackageName = `${pkg.name}-dynamic`;
const packagesToEmbed = (opts.embedPackage || []) as string[];
const allowNative = (opts.allowNativePackage || []) as string[];
const suppressNative = (opts.suppressNativePackage || []) as string[];
const monoRepoPackages = await getPackages(paths.targetDir);
const embeddedResolvedPackages = await searchEmbedded(
pkg,
Expand Down Expand Up @@ -119,6 +122,30 @@ ${
}`,
);

if (suppressNative.length > 0) {
for (const toSuppress of suppressNative) {
await fs.mkdirs(path.join(target, 'embedded', toSuppress));
await fs.writeFile(
path.join(target, 'embedded', toSuppress, 'package.json'),
JSON.stringify(
{
name: toSuppress,
main: 'index.js',
},
undefined,
2,
),
);
await fs.writeFile(
path.join(target, 'embedded', toSuppress, 'index.js'),
`
throw new Error(
'The package "${toSuppress}" has been marked as a native module and removed from this dynamic plugin package "${derivedPackageName}", as native modules are not currently supported by dynamic plugins'
);`,
);
}
}

const embeddedPeerDependencies: {
[key: string]: string;
} = {};
Expand Down Expand Up @@ -205,11 +232,14 @@ ${
})(path.join(embeddedDestDir, 'package.json'));
}

const embeddedDependenciesResolutions: { [key: string]: any } = {};
embeddedResolvedPackages.map(ep => {
embeddedDependenciesResolutions[ep.packageName] =
`file:./${embeddedPackageRelativePath(ep)}`;
});
const embeddedDependenciesResolutions = embeddedResolvedPackages.reduce(
(resolutions, ep) => {
resolutions[ep.packageName] = `file:./${embeddedPackageRelativePath(ep)}`;

return resolutions;
},
{} as { [key: string]: `file:./${string}` },
);

if (opts.build) {
Task.log(`Building main package`);
Expand Down Expand Up @@ -247,7 +277,7 @@ ${
monoRepoPackages,
sharedPackages: sharedPackagesRules,
overridding: {
name: `${pkg.name}-dynamic`,
name: derivedPackageName,
bundleDependencies: true,
// We remove scripts, because they do not make sense for this derived package.
// They even bring errors, especially the pre-pack and post-pack ones:
Expand All @@ -256,7 +286,14 @@ ${
// which are related to the packaging of the original static package.
scripts: {},
},
additionalResolutions: embeddedDependenciesResolutions,
additionalResolutions: {
...embeddedDependenciesResolutions,
...suppressNative
.map((nativePkg: string) => ({
[nativePkg]: path.join('file:./embedded', nativePkg),
}))
.reduce((prev, curr) => ({ ...prev, ...curr }), {}),
},
after(mainPkg) {
if (Object.keys(embeddedPeerDependencies).length === 0) {
return;
Expand Down Expand Up @@ -407,9 +444,12 @@ ${

// Check whether private dependencies contain native modules, and fail for now (not supported).
const nativePackages: string[] = [];
for await (const n of gatherNativeModules(target)) {
nativePackages.push(n);
for await (const nativePkg of gatherNativeModules(target)) {
if (!allowNative.includes(nativePkg)) {
nativePackages.push(nativePkg);
}
}

if (nativePackages.length > 0) {
throw new Error(
`Dynamic plugins do not support native plugins. the following native modules have been transitively detected:${chalk.cyan(
Expand Down
8 changes: 8 additions & 0 deletions packages/cli/src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ export function registerScriptCommand(program: Command) {
},
{},
)
.option(
'--allow-native-package [package-name...]',
'Optional list of native packages names that can be included in the exported plugin',
)
.option(
'--suppress-native-package [package-name...]',
'Optional list of native package names to be excluded from the exported plugin',
)
.option(
'--no-install',
'Do not run `yarn install` to fill the dynamic plugin `node_modules` folder (backend plugin only).',
Expand Down

0 comments on commit abd9dec

Please sign in to comment.