@backstage/backend-dynamic-feature-service 0.8.8 → 0.8.9-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# @backstage/backend-dynamic-feature-service
|
|
2
2
|
|
|
3
|
+
## 0.8.9-next.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
- @backstage/backend-defaults@0.18.2-next.1
|
|
9
|
+
- @backstage/plugin-catalog-backend@4.0.3-next.1
|
|
10
|
+
- @backstage/cli-node@0.3.6-next.1
|
|
11
|
+
- @backstage/plugin-events-backend@0.6.8-next.1
|
|
12
|
+
- @backstage/plugin-events-node@0.5.0-next.1
|
|
13
|
+
- @backstage/plugin-auth-node@0.7.8-next.1
|
|
14
|
+
- @backstage/plugin-scaffolder-node@0.13.9-next.1
|
|
15
|
+
|
|
16
|
+
## 0.8.9-next.0
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- c999b77: Dynamic backend plugins can now require the packages they share with the backend when those packages are not in the root `node_modules`, as with the pnpm `isolated` node linker. They are found through the backend package and through this package. With the default pnpm hoisting, this includes the packages that pnpm hoists into `node_modules/.pnpm/node_modules`. With `hoist: false`, only the direct dependencies of the backend package and of this package are found. Everything that was searched before is still searched first, so a module that was found before is found in the same place. The exception is plugins inside the Backstage root on Windows, which did not search the root `node_modules` before, other than through `NODE_PATH`. It is now searched in the same order as on other platforms.
|
|
21
|
+
- Updated dependencies
|
|
22
|
+
- @backstage/backend-defaults@0.18.2-next.0
|
|
23
|
+
- @backstage/plugin-catalog-backend@4.0.3-next.0
|
|
24
|
+
- @backstage/cli-node@0.3.6-next.0
|
|
25
|
+
- @backstage/plugin-events-backend@0.6.8-next.0
|
|
26
|
+
- @backstage/plugin-auth-node@0.7.8-next.0
|
|
27
|
+
- @backstage/plugin-permission-node@0.11.6-next.0
|
|
28
|
+
- @backstage/plugin-search-backend-node@1.4.10-next.0
|
|
29
|
+
- @backstage/backend-plugin-api@1.11.1-next.0
|
|
30
|
+
- @backstage/plugin-events-node@0.4.28-next.0
|
|
31
|
+
- @backstage/plugin-scaffolder-node@0.13.9-next.0
|
|
32
|
+
- @backstage/backend-openapi-utils@0.7.4-next.0
|
|
33
|
+
- @backstage/plugin-app-node@0.1.51-next.0
|
|
34
|
+
|
|
3
35
|
## 0.8.8
|
|
4
36
|
|
|
5
37
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -35,6 +35,14 @@ The service consists of several key components:
|
|
|
35
35
|
3. **Loading**: The module loader loads the plugin code
|
|
36
36
|
4. **Integration**: Plugins are registered as Backstage features and made available to the backend
|
|
37
37
|
|
|
38
|
+
### Module Resolution
|
|
39
|
+
|
|
40
|
+
When a backend dynamic plugin requires a module, it is resolved from the plugin's own `node_modules` first, then from the `node_modules` of the Backstage root, and then from the global folders of Node.js, which start with the directories in `NODE_PATH`. Plugins outside of the Backstage root reach the root `node_modules` through `NODE_PATH`, so for them the order of `NODE_PATH` applies. When `NODE_PATH` doesn't include it, the root `node_modules` is searched right after the global folders.
|
|
41
|
+
|
|
42
|
+
Modules that are not found in these places are resolved from the host backend, through the `node_modules` directories of the backend package and of this package within the Backstage root. The backend package is found through the entry point of the process and the working directory. If the backend is started by another program, such as a process manager, use the backend package directory as its working directory, and adjust relative paths such as `--config` arguments.
|
|
43
|
+
|
|
44
|
+
This lets a plugin require the packages it shares with the host when the package manager does not link them into the root `node_modules`, as with the pnpm `isolated` node linker. With the default pnpm hoisting, this includes the packages that pnpm hoists into `node_modules/.pnpm/node_modules`. With `hoist: false`, only the direct dependencies of the backend package and of this package are found.
|
|
45
|
+
|
|
38
46
|
## Usage
|
|
39
47
|
|
|
40
48
|
### Basic Setup
|
|
@@ -109,7 +117,7 @@ mkdir -p /path/to/dynamic-plugins-root/my-backstage-plugin
|
|
|
109
117
|
tar -xzf package.tgz -C /path/to/dynamic-plugins-root/my-backstage-plugin --strip-components=1
|
|
110
118
|
```
|
|
111
119
|
|
|
112
|
-
**Why this works:** The plugin can resolve all its dependencies from the main application
|
|
120
|
+
**Why this works:** The plugin can resolve all its dependencies from the main application. See [Module Resolution](#module-resolution).
|
|
113
121
|
|
|
114
122
|
**Reality:** Most plugins have private dependencies not available in the main application, so this approach has limited applicability.
|
|
115
123
|
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var cliCommon = require('@backstage/cli-common');
|
|
4
|
+
var fs = require('node:fs');
|
|
3
5
|
var path = require('node:path');
|
|
4
6
|
|
|
5
7
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
6
8
|
|
|
9
|
+
var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|
7
10
|
var path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
8
11
|
|
|
9
12
|
class CommonJSModuleLoader {
|
|
@@ -14,11 +17,22 @@ class CommonJSModuleLoader {
|
|
|
14
17
|
this.module = require("node:module");
|
|
15
18
|
}
|
|
16
19
|
async bootstrap(backstageRoot, dynamicPluginsPaths, scannedPluginManifests) {
|
|
17
|
-
const backstageRootNodeModulesPath =
|
|
20
|
+
const backstageRootNodeModulesPath = path__default.default.join(
|
|
21
|
+
backstageRoot,
|
|
22
|
+
"node_modules"
|
|
23
|
+
);
|
|
18
24
|
const dynamicNodeModulesPaths = [
|
|
19
25
|
...dynamicPluginsPaths.map((p) => path__default.default.resolve(p, "node_modules"))
|
|
20
26
|
];
|
|
21
27
|
const oldNodeModulePaths = this.module._nodeModulePaths;
|
|
28
|
+
const globalPaths = (this.module.globalPaths ?? []).map(
|
|
29
|
+
(p) => path__default.default.resolve(p)
|
|
30
|
+
);
|
|
31
|
+
const hostNodeModulesPaths = getHostNodeModulesPaths(
|
|
32
|
+
backstageRoot,
|
|
33
|
+
oldNodeModulePaths
|
|
34
|
+
);
|
|
35
|
+
const previousSearchPaths = /* @__PURE__ */ new WeakMap();
|
|
22
36
|
this.module._nodeModulePaths = (from) => {
|
|
23
37
|
const result = oldNodeModulePaths(from);
|
|
24
38
|
if (!dynamicPluginsPaths.some((p) => from.startsWith(p))) {
|
|
@@ -27,15 +41,37 @@ class CommonJSModuleLoader {
|
|
|
27
41
|
const filtered = result.filter((nodeModulePath) => {
|
|
28
42
|
return nodeModulePath === backstageRootNodeModulesPath || dynamicNodeModulesPaths.some((p) => nodeModulePath.startsWith(p));
|
|
29
43
|
});
|
|
44
|
+
const searchPaths = Array.from(
|
|
45
|
+
/* @__PURE__ */ new Set([
|
|
46
|
+
...filtered,
|
|
47
|
+
...globalPaths,
|
|
48
|
+
backstageRootNodeModulesPath,
|
|
49
|
+
...hostNodeModulesPaths
|
|
50
|
+
])
|
|
51
|
+
);
|
|
52
|
+
previousSearchPaths.set(searchPaths, filtered);
|
|
30
53
|
this.options.logger.debug(
|
|
31
|
-
`Overriding node_modules search path for dynamic plugin ${from} to: ${
|
|
54
|
+
`Overriding node_modules search path for dynamic plugin ${from} to: ${searchPaths}`
|
|
32
55
|
);
|
|
33
|
-
return
|
|
56
|
+
return searchPaths;
|
|
34
57
|
};
|
|
35
58
|
const oldResolveFileName = this.module._resolveFilename;
|
|
36
59
|
this.module._resolveFilename = (request, mod, _, options) => {
|
|
60
|
+
const resolvingPackageJsonViaResolvePackagePath = request?.endsWith("/package.json") && /[/\\](?:@backstage|packages)[/\\]backend-plugin-api(?:[/\\]|$)/.test(
|
|
61
|
+
mod?.path ?? ""
|
|
62
|
+
);
|
|
63
|
+
const previousPaths = resolvingPackageJsonViaResolvePackagePath && !options?.paths ? mod?.paths && previousSearchPaths.get(mod.paths) : void 0;
|
|
37
64
|
let errorToThrow;
|
|
38
65
|
try {
|
|
66
|
+
if (previousPaths) {
|
|
67
|
+
const searchPaths = mod.paths;
|
|
68
|
+
mod.paths = previousPaths;
|
|
69
|
+
try {
|
|
70
|
+
return oldResolveFileName(request, mod, _, options);
|
|
71
|
+
} finally {
|
|
72
|
+
mod.paths = searchPaths;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
39
75
|
return oldResolveFileName(request, mod, _, options);
|
|
40
76
|
} catch (e) {
|
|
41
77
|
errorToThrow = e;
|
|
@@ -44,9 +80,6 @@ class CommonJSModuleLoader {
|
|
|
44
80
|
e instanceof Error ? e : void 0
|
|
45
81
|
);
|
|
46
82
|
}
|
|
47
|
-
const resolvingPackageJsonViaResolvePackagePath = request?.endsWith("/package.json") && /[/\\](?:@backstage|packages)[/\\]backend-plugin-api(?:[/\\]|$)/.test(
|
|
48
|
-
mod?.path ?? ""
|
|
49
|
-
);
|
|
50
83
|
if (!resolvingPackageJsonViaResolvePackagePath) {
|
|
51
84
|
throw errorToThrow;
|
|
52
85
|
}
|
|
@@ -74,6 +107,16 @@ class CommonJSModuleLoader {
|
|
|
74
107
|
return resolvedPath;
|
|
75
108
|
}
|
|
76
109
|
}
|
|
110
|
+
if (previousPaths) {
|
|
111
|
+
try {
|
|
112
|
+
const resolvedPath = oldResolveFileName(request, mod, _, options);
|
|
113
|
+
this.options.logger.info(
|
|
114
|
+
`Resolved '${request}' at ${resolvedPath} in the host backend`
|
|
115
|
+
);
|
|
116
|
+
return resolvedPath;
|
|
117
|
+
} catch {
|
|
118
|
+
}
|
|
119
|
+
}
|
|
77
120
|
throw errorToThrow;
|
|
78
121
|
};
|
|
79
122
|
}
|
|
@@ -81,6 +124,53 @@ class CommonJSModuleLoader {
|
|
|
81
124
|
return await this.module.prototype.require(packagePath);
|
|
82
125
|
}
|
|
83
126
|
}
|
|
127
|
+
function getHostNodeModulesPaths(backstageRoot, nodeModulePaths) {
|
|
128
|
+
const dirs = new Array();
|
|
129
|
+
for (const startPath of [
|
|
130
|
+
require.main?.filename,
|
|
131
|
+
process.argv[1],
|
|
132
|
+
process.cwd()
|
|
133
|
+
]) {
|
|
134
|
+
const dir = startPath && getDirectory(path__default.default.resolve(startPath));
|
|
135
|
+
if (dir && !isInInstalledPackage(backstageRoot, dir)) {
|
|
136
|
+
dirs.push(dir);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const paths = /* @__PURE__ */ new Set([
|
|
140
|
+
...dirs.flatMap((dir) => nodeModulePaths(dir)),
|
|
141
|
+
// The lookup chain of this module
|
|
142
|
+
...module.paths ?? []
|
|
143
|
+
]);
|
|
144
|
+
return Array.from(paths).filter((p) => {
|
|
145
|
+
try {
|
|
146
|
+
return cliCommon.isChildPath(backstageRoot, p);
|
|
147
|
+
} catch {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
function getDirectory(p) {
|
|
153
|
+
try {
|
|
154
|
+
const stats = fs__default.default.statSync(p, { throwIfNoEntry: false });
|
|
155
|
+
if (!stats) {
|
|
156
|
+
return void 0;
|
|
157
|
+
}
|
|
158
|
+
return stats.isDirectory() ? p : path__default.default.dirname(p);
|
|
159
|
+
} catch {
|
|
160
|
+
return void 0;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function isInInstalledPackage(backstageRoot, dir) {
|
|
164
|
+
try {
|
|
165
|
+
const relativeDir = path__default.default.relative(
|
|
166
|
+
fs__default.default.realpathSync(backstageRoot),
|
|
167
|
+
fs__default.default.realpathSync(dir)
|
|
168
|
+
);
|
|
169
|
+
return relativeDir.split(path__default.default.sep).includes("node_modules");
|
|
170
|
+
} catch {
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
84
174
|
|
|
85
175
|
exports.CommonJSModuleLoader = CommonJSModuleLoader;
|
|
86
176
|
//# sourceMappingURL=CommonJSModuleLoader.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommonJSModuleLoader.cjs.js","sources":["../../src/loader/CommonJSModuleLoader.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ModuleLoader } from './types';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport path from 'node:path';\nimport { ScannedPluginManifest } from '../scanner';\n\n/**\n * @public\n */\nexport type CommonJSModuleLoaderOptions = {\n logger: LoggerService;\n dynamicPluginPackageNameSuffixes?: String[];\n customResolveDynamicPackage?: (\n logger: LoggerService,\n searchedPackageName: string,\n scannedPluginManifests: Map<string, ScannedPluginManifest>,\n ) => string | undefined;\n};\n\n/**\n * @public\n */\nexport class CommonJSModuleLoader implements ModuleLoader {\n private module: any;\n public readonly options: CommonJSModuleLoaderOptions;\n\n constructor(options: CommonJSModuleLoaderOptions) {\n this.options = options;\n this.module = require('node:module');\n }\n\n async bootstrap(\n backstageRoot: string,\n dynamicPluginsPaths: string[],\n scannedPluginManifests: Map<string, ScannedPluginManifest>,\n ): Promise<void> {\n const backstageRootNodeModulesPath = `${backstageRoot}/node_modules`;\n const dynamicNodeModulesPaths = [\n ...dynamicPluginsPaths.map(p => path.resolve(p, 'node_modules')),\n ];\n const oldNodeModulePaths = this.module._nodeModulePaths;\n this.module._nodeModulePaths = (from: string): string[] => {\n const result: string[] = oldNodeModulePaths(from);\n if (!dynamicPluginsPaths.some(p => from.startsWith(p))) {\n return result;\n }\n const filtered = result.filter(nodeModulePath => {\n return (\n nodeModulePath === backstageRootNodeModulesPath ||\n dynamicNodeModulesPaths.some(p => nodeModulePath.startsWith(p))\n );\n });\n this.options.logger.debug(\n `Overriding node_modules search path for dynamic plugin ${from} to: ${filtered}`,\n );\n return filtered;\n };\n\n // The whole piece of code below is a way to accommodate the limitations of\n // the current `resolvePackagePath` implementation, which cannot be provided\n // some custom locations where it should find the assets of some given packages.\n //\n // Since the packages for dynamic plugins are not located in the main backstage\n // monorepo structure, and since dynamic plugins could also be repackaged\n // (typically renamed with a `-dynamic` suffix), for now we have to customize\n // module file name resolution here to support these use-cases.\n //\n // This might not be necessary anymore according to future enhancements to the\n // `resolvePackagePath` feature.\n const oldResolveFileName = this.module._resolveFilename;\n this.module._resolveFilename = (\n request: string,\n mod: NodeModule,\n _: boolean,\n options: any,\n ): any => {\n let errorToThrow: any;\n try {\n return oldResolveFileName(request, mod, _, options);\n } catch (e) {\n errorToThrow = e;\n this.options.logger.debug(\n `Could not resolve '${request}' inside the Core backstage backend application`,\n e instanceof Error ? e : undefined,\n );\n }\n\n // Is this a `resolvePackagePath` call from `@backstage/backend-plugin-api`?\n // This covers both the host application's copy and a bundled copy living\n // inside a dynamic plugin's own node_modules.\n // The regex matches mod.path against the various ways the package can be resolved on disk\n // (with optional subdirectory such as /src or /dist after the package name):\n // - .../node_modules/@backstage/backend-plugin-api[/...] (npm-installed)\n // - .../<plugin>/node_modules/@backstage/backend-plugin-api[/...] (bundled)\n // - .../packages/backend-plugin-api[/...] (symlinked workspace in monorepo)\n const resolvingPackageJsonViaResolvePackagePath =\n request?.endsWith('/package.json') &&\n /[/\\\\](?:@backstage|packages)[/\\\\]backend-plugin-api(?:[/\\\\]|$)/.test(\n mod?.path ?? '',\n );\n\n if (!resolvingPackageJsonViaResolvePackagePath) {\n throw errorToThrow;\n }\n\n this.options.logger.info(\n `Resolving '${request}' in the dynamic backend plugins`,\n );\n const searchedPackageName = request.replace(/\\/package.json$/, '');\n\n // First search for a dynamic plugin package matching the expected package name,\n // taking in account accepted dynamic plugin package name suffixes\n // (suffix accepted by default is '-dynamic').\n const searchedPackageNamesWithSuffixes = (\n this.options.dynamicPluginPackageNameSuffixes ?? ['-dynamic']\n ).map(s => `${searchedPackageName}${s}`);\n for (const [realPath, pkg] of scannedPluginManifests.entries()) {\n if (\n [searchedPackageName, ...searchedPackageNamesWithSuffixes].includes(\n pkg.name,\n )\n ) {\n const resolvedPath = path.resolve(realPath, 'package.json');\n this.options.logger.info(`Resolved '${request}' at ${resolvedPath}`);\n return resolvedPath;\n }\n }\n\n // If a custom resolution is provided, use it.\n // This allows accommodating alternate ways to package dynamic plugins:\n // static plugin package wrapped inside a distinct dynamic plugin package for example.\n if (this.options.customResolveDynamicPackage) {\n const resolvedPath = this.options.customResolveDynamicPackage(\n this.options.logger,\n searchedPackageName,\n scannedPluginManifests,\n );\n if (resolvedPath) {\n return resolvedPath;\n }\n }\n throw errorToThrow;\n };\n }\n\n async load(packagePath: string): Promise<any> {\n return await this.module.prototype.require(packagePath);\n }\n}\n"],"names":["path"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CommonJSModuleLoader.cjs.js","sources":["../../src/loader/CommonJSModuleLoader.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ModuleLoader } from './types';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { isChildPath } from '@backstage/cli-common';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { ScannedPluginManifest } from '../scanner';\n\n/**\n * @public\n */\nexport type CommonJSModuleLoaderOptions = {\n logger: LoggerService;\n dynamicPluginPackageNameSuffixes?: String[];\n customResolveDynamicPackage?: (\n logger: LoggerService,\n searchedPackageName: string,\n scannedPluginManifests: Map<string, ScannedPluginManifest>,\n ) => string | undefined;\n};\n\n/**\n * @public\n */\nexport class CommonJSModuleLoader implements ModuleLoader {\n private module: any;\n public readonly options: CommonJSModuleLoaderOptions;\n\n constructor(options: CommonJSModuleLoaderOptions) {\n this.options = options;\n this.module = require('node:module');\n }\n\n async bootstrap(\n backstageRoot: string,\n dynamicPluginsPaths: string[],\n scannedPluginManifests: Map<string, ScannedPluginManifest>,\n ): Promise<void> {\n const backstageRootNodeModulesPath = path.join(\n backstageRoot,\n 'node_modules',\n );\n const dynamicNodeModulesPaths = [\n ...dynamicPluginsPaths.map(p => path.resolve(p, 'node_modules')),\n ];\n const oldNodeModulePaths = this.module._nodeModulePaths;\n // After the node_modules lookup chain, Node.js searches its global\n // folders, which start with the NODE_PATH entries. Dynamic plugins outside\n // of the Backstage root reach the root node_modules through NODE_PATH.\n const globalPaths: string[] = (this.module.globalPaths ?? []).map(\n (p: string) => path.resolve(p),\n );\n // Some package managers, for example pnpm with the isolated linker, do not\n // link every package into the root node_modules. The modules that a\n // dynamic plugin shares with the host are then only visible from the\n // backend package, or from this package.\n const hostNodeModulesPaths = getHostNodeModulesPaths(\n backstageRoot,\n oldNodeModulePaths,\n );\n // The paths that were searched before the host was added, for each list\n // of search paths returned below\n const previousSearchPaths = new WeakMap<string[], string[]>();\n this.module._nodeModulePaths = (from: string): string[] => {\n const result: string[] = oldNodeModulePaths(from);\n if (!dynamicPluginsPaths.some(p => from.startsWith(p))) {\n return result;\n }\n const filtered = result.filter(nodeModulePath => {\n return (\n nodeModulePath === backstageRootNodeModulesPath ||\n dynamicNodeModulesPaths.some(p => nodeModulePath.startsWith(p))\n );\n });\n // The host comes after everything that was searched before, so that a\n // module that was found before is still found in the same place. Node.js\n // appends its global folders again after these paths, so a module that\n // is missing everywhere is looked for in them twice.\n const searchPaths = Array.from(\n new Set([\n ...filtered,\n ...globalPaths,\n backstageRootNodeModulesPath,\n ...hostNodeModulesPaths,\n ]),\n );\n previousSearchPaths.set(searchPaths, filtered);\n this.options.logger.debug(\n `Overriding node_modules search path for dynamic plugin ${from} to: ${searchPaths}`,\n );\n return searchPaths;\n };\n\n // The whole piece of code below is a way to accommodate the limitations of\n // the current `resolvePackagePath` implementation, which cannot be provided\n // some custom locations where it should find the assets of some given packages.\n //\n // Since the packages for dynamic plugins are not located in the main backstage\n // monorepo structure, and since dynamic plugins could also be repackaged\n // (typically renamed with a `-dynamic` suffix), for now we have to customize\n // module file name resolution here to support these use-cases.\n //\n // This might not be necessary anymore according to future enhancements to the\n // `resolvePackagePath` feature.\n const oldResolveFileName = this.module._resolveFilename;\n this.module._resolveFilename = (\n request: string,\n mod: NodeModule,\n _: boolean,\n options: any,\n ): any => {\n // Is this a `resolvePackagePath` call from `@backstage/backend-plugin-api`?\n // This covers both the host application's copy and a bundled copy living\n // inside a dynamic plugin's own node_modules.\n // The regex matches mod.path against the various ways the package can be resolved on disk\n // (with optional subdirectory such as /src or /dist after the package name):\n // - .../node_modules/@backstage/backend-plugin-api[/...] (npm-installed)\n // - .../<plugin>/node_modules/@backstage/backend-plugin-api[/...] (bundled)\n // - .../packages/backend-plugin-api[/...] (symlinked workspace in monorepo)\n const resolvingPackageJsonViaResolvePackagePath =\n request?.endsWith('/package.json') &&\n /[/\\\\](?:@backstage|packages)[/\\\\]backend-plugin-api(?:[/\\\\]|$)/.test(\n mod?.path ?? '',\n );\n\n // A bundled copy of `@backstage/backend-plugin-api` in a dynamic plugin\n // searches the host last, after the dynamic plugin packages below, so\n // that it finds the same package as before the host was added. This\n // covers calls without explicit paths, which is how\n // `resolvePackagePath` resolves.\n const previousPaths =\n resolvingPackageJsonViaResolvePackagePath && !options?.paths\n ? mod?.paths && previousSearchPaths.get(mod.paths)\n : undefined;\n\n let errorToThrow: any;\n try {\n if (previousPaths) {\n const searchPaths = mod.paths;\n mod.paths = previousPaths;\n try {\n return oldResolveFileName(request, mod, _, options);\n } finally {\n mod.paths = searchPaths;\n }\n }\n return oldResolveFileName(request, mod, _, options);\n } catch (e) {\n errorToThrow = e;\n this.options.logger.debug(\n `Could not resolve '${request}' inside the Core backstage backend application`,\n e instanceof Error ? e : undefined,\n );\n }\n\n if (!resolvingPackageJsonViaResolvePackagePath) {\n throw errorToThrow;\n }\n\n this.options.logger.info(\n `Resolving '${request}' in the dynamic backend plugins`,\n );\n const searchedPackageName = request.replace(/\\/package.json$/, '');\n\n // First search for a dynamic plugin package matching the expected package name,\n // taking in account accepted dynamic plugin package name suffixes\n // (suffix accepted by default is '-dynamic').\n const searchedPackageNamesWithSuffixes = (\n this.options.dynamicPluginPackageNameSuffixes ?? ['-dynamic']\n ).map(s => `${searchedPackageName}${s}`);\n for (const [realPath, pkg] of scannedPluginManifests.entries()) {\n if (\n [searchedPackageName, ...searchedPackageNamesWithSuffixes].includes(\n pkg.name,\n )\n ) {\n const resolvedPath = path.resolve(realPath, 'package.json');\n this.options.logger.info(`Resolved '${request}' at ${resolvedPath}`);\n return resolvedPath;\n }\n }\n\n // If a custom resolution is provided, use it.\n // This allows accommodating alternate ways to package dynamic plugins:\n // static plugin package wrapped inside a distinct dynamic plugin package for example.\n if (this.options.customResolveDynamicPackage) {\n const resolvedPath = this.options.customResolveDynamicPackage(\n this.options.logger,\n searchedPackageName,\n scannedPluginManifests,\n );\n if (resolvedPath) {\n return resolvedPath;\n }\n }\n\n // Last, the host\n if (previousPaths) {\n try {\n const resolvedPath = oldResolveFileName(request, mod, _, options);\n this.options.logger.info(\n `Resolved '${request}' at ${resolvedPath} in the host backend`,\n );\n return resolvedPath;\n } catch {\n // The error from the first attempt is the one to report\n }\n }\n throw errorToThrow;\n };\n }\n\n async load(packagePath: string): Promise<any> {\n return await this.module.prototype.require(packagePath);\n }\n}\n\n/**\n * Returns the node_modules directories that the host backend resolves modules\n * from, limited to those within the Backstage root. These are the lookup\n * chains of the backend package, found through the entry point of the process\n * and the working directory, and of this package, which reaches the packages\n * that a package manager keeps out of the root node_modules. An entry point in\n * an installed package, such as a process manager that starts the backend, is\n * not the backend package, so its lookup chain is not used.\n */\nfunction getHostNodeModulesPaths(\n backstageRoot: string,\n nodeModulePaths: (from: string) => string[],\n): string[] {\n const dirs = new Array<string>();\n // The main module is not set when the entry point is an ES module, so the\n // script path is also used\n for (const startPath of [\n require.main?.filename,\n process.argv[1],\n process.cwd(),\n ]) {\n const dir = startPath && getDirectory(path.resolve(startPath));\n if (dir && !isInInstalledPackage(backstageRoot, dir)) {\n dirs.push(dir);\n }\n }\n const paths = new Set([\n ...dirs.flatMap(dir => nodeModulePaths(dir)),\n // The lookup chain of this module\n ...(module.paths ?? []),\n ]);\n return Array.from(paths).filter(p => {\n // Real paths cannot be resolved for directories that cannot be read\n try {\n return isChildPath(backstageRoot, p);\n } catch {\n return false;\n }\n });\n}\n\n// The given directory, or the directory of the given file. Paths that do not\n// exist or cannot be read are skipped, since the host is only a fallback.\nfunction getDirectory(p: string): string | undefined {\n try {\n const stats = fs.statSync(p, { throwIfNoEntry: false });\n if (!stats) {\n return undefined;\n }\n return stats.isDirectory() ? p : path.dirname(p);\n } catch {\n return undefined;\n }\n}\n\n// Whether the directory is inside a node_modules directory of the Backstage\n// root, or cannot be read. Workspace packages, such as the backend package,\n// are never inside node_modules.\nfunction isInInstalledPackage(backstageRoot: string, dir: string): boolean {\n try {\n const relativeDir = path.relative(\n fs.realpathSync(backstageRoot),\n fs.realpathSync(dir),\n );\n return relativeDir.split(path.sep).includes('node_modules');\n } catch {\n return true;\n }\n}\n"],"names":["path","isChildPath","fs"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/backend-dynamic-feature-service",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.9-next.1",
|
|
4
4
|
"description": "Backstage dynamic feature service",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "node-library"
|
|
@@ -51,25 +51,25 @@
|
|
|
51
51
|
"test": "backstage-cli package test"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@backstage/backend-defaults": "
|
|
55
|
-
"@backstage/backend-openapi-utils": "
|
|
56
|
-
"@backstage/backend-plugin-api": "
|
|
57
|
-
"@backstage/cli-common": "
|
|
58
|
-
"@backstage/cli-node": "
|
|
59
|
-
"@backstage/config": "
|
|
60
|
-
"@backstage/config-loader": "
|
|
61
|
-
"@backstage/errors": "
|
|
62
|
-
"@backstage/plugin-app-node": "
|
|
63
|
-
"@backstage/plugin-auth-node": "
|
|
64
|
-
"@backstage/plugin-catalog-backend": "
|
|
65
|
-
"@backstage/plugin-events-backend": "
|
|
66
|
-
"@backstage/plugin-events-node": "
|
|
67
|
-
"@backstage/plugin-permission-common": "
|
|
68
|
-
"@backstage/plugin-permission-node": "
|
|
69
|
-
"@backstage/plugin-scaffolder-node": "
|
|
70
|
-
"@backstage/plugin-search-backend-node": "
|
|
71
|
-
"@backstage/plugin-search-common": "
|
|
72
|
-
"@backstage/types": "
|
|
54
|
+
"@backstage/backend-defaults": "0.18.2-next.1",
|
|
55
|
+
"@backstage/backend-openapi-utils": "0.7.4-next.0",
|
|
56
|
+
"@backstage/backend-plugin-api": "1.11.1-next.0",
|
|
57
|
+
"@backstage/cli-common": "0.3.2",
|
|
58
|
+
"@backstage/cli-node": "0.3.6-next.1",
|
|
59
|
+
"@backstage/config": "1.3.10",
|
|
60
|
+
"@backstage/config-loader": "1.11.4",
|
|
61
|
+
"@backstage/errors": "1.3.2",
|
|
62
|
+
"@backstage/plugin-app-node": "0.1.51-next.0",
|
|
63
|
+
"@backstage/plugin-auth-node": "0.7.8-next.1",
|
|
64
|
+
"@backstage/plugin-catalog-backend": "4.0.3-next.1",
|
|
65
|
+
"@backstage/plugin-events-backend": "0.6.8-next.1",
|
|
66
|
+
"@backstage/plugin-events-node": "0.5.0-next.1",
|
|
67
|
+
"@backstage/plugin-permission-common": "0.9.12",
|
|
68
|
+
"@backstage/plugin-permission-node": "0.11.6-next.0",
|
|
69
|
+
"@backstage/plugin-scaffolder-node": "0.13.9-next.1",
|
|
70
|
+
"@backstage/plugin-search-backend-node": "1.4.10-next.0",
|
|
71
|
+
"@backstage/plugin-search-common": "1.2.26",
|
|
72
|
+
"@backstage/types": "1.2.2",
|
|
73
73
|
"@manypkg/get-packages": "^1.1.3",
|
|
74
74
|
"@module-federation/sdk": "~2.8.2",
|
|
75
75
|
"chokidar": "^3.5.3",
|
|
@@ -80,11 +80,11 @@
|
|
|
80
80
|
"winston": "^3.2.1"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
|
-
"@backstage/backend-app-api": "
|
|
84
|
-
"@backstage/backend-test-utils": "
|
|
85
|
-
"@backstage/cli": "
|
|
86
|
-
"@backstage/plugin-app-backend": "
|
|
87
|
-
"@backstage/repo-tools": "
|
|
83
|
+
"@backstage/backend-app-api": "1.9.0-next.0",
|
|
84
|
+
"@backstage/backend-test-utils": "1.11.9-next.1",
|
|
85
|
+
"@backstage/cli": "0.36.8-next.1",
|
|
86
|
+
"@backstage/plugin-app-backend": "0.5.20-next.0",
|
|
87
|
+
"@backstage/repo-tools": "0.19.3-next.0",
|
|
88
88
|
"@types/express": "^4.17.6",
|
|
89
89
|
"triple-beam": "^1.4.1",
|
|
90
90
|
"wait-for-expect": "^4.0.0"
|