UNPKG

8.15 kBJavaScriptView Raw
1'use strict';
2
3var fs = require('fs-extra');
4require('semver');
5require('@yarnpkg/parsers');
6require('@yarnpkg/lockfile');
7var packages = require('./packages-f8fc8f67.cjs.js');
8var index = require('./index-09611511.cjs.js');
9var chalk = require('chalk');
10var sortBy = require('lodash/sortBy');
11var groupBy = require('lodash/groupBy');
12var run = require('./run-a95417b1.cjs.js');
13require('minimatch');
14require('@manypkg/get-packages');
15require('commander');
16require('@backstage/cli-common');
17require('@backstage/errors');
18require('child_process');
19require('util');
20
21function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
22
23var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
24var chalk__default = /*#__PURE__*/_interopDefaultLegacy(chalk);
25var sortBy__default = /*#__PURE__*/_interopDefaultLegacy(sortBy);
26var groupBy__default = /*#__PURE__*/_interopDefaultLegacy(groupBy);
27
28function createStepDefinition(config) {
29 return config;
30}
31
32class AppRouteStep {
33 constructor(data) {
34 this.data = data;
35 }
36 async run() {
37 var _a;
38 const { path, element, packageName } = this.data;
39 const appTsxPath = index.paths.resolveTargetRoot("packages/app/src/App.tsx");
40 const contents = await fs__default["default"].readFile(appTsxPath, "utf-8");
41 let failed = false;
42 const contentsWithRoute = contents.replace(/(\s*)<\/FlatRoutes>/, `$1 <Route path="${path}" element={${element}} />$1</FlatRoutes>`);
43 if (contentsWithRoute === contents) {
44 failed = true;
45 }
46 const componentName = (_a = element.match(/[A-Za-z0-9]+/)) == null ? void 0 : _a[0];
47 if (!componentName) {
48 throw new Error(`Could not find component name in ${element}`);
49 }
50 const contentsWithImport = contentsWithRoute.replace(/^import /m, `import { ${componentName} } from '${packageName}';
51import `);
52 if (contentsWithImport === contentsWithRoute) {
53 failed = true;
54 }
55 if (failed) {
56 console.log("Failed to automatically add a route to package/app/src/App.tsx");
57 console.log(`Action needed, add the following:`);
58 console.log(`1. import { ${componentName} } from '${packageName}';`);
59 console.log(`2. <Route path="${path}" element={${element}} />`);
60 } else {
61 await fs__default["default"].writeFile(appTsxPath, contentsWithImport);
62 }
63 }
64}
65const appRoute = createStepDefinition({
66 type: "app-route",
67 deserialize(obj, pkg) {
68 const { path, element } = obj;
69 if (!path || typeof path !== "string") {
70 throw new Error("Invalid install step, 'path' must be a string");
71 }
72 if (!element || typeof element !== "string") {
73 throw new Error("Invalid install step, 'element' must be a string");
74 }
75 return new AppRouteStep({ path, element, packageName: pkg.name });
76 },
77 create(data) {
78 return new AppRouteStep(data);
79 }
80});
81
82class DependenciesStep {
83 constructor(data) {
84 this.data = data;
85 }
86 async run() {
87 const { dependencies: dependencies2 } = this.data;
88 const byTarget = groupBy__default["default"](dependencies2, "target");
89 for (const [target, deps] of Object.entries(byTarget)) {
90 const pkgPath = index.paths.resolveTargetRoot(target, "package.json");
91 const pkgJson = await fs__default["default"].readJson(pkgPath);
92 const depTypes = /* @__PURE__ */ new Set();
93 for (const dep of deps) {
94 depTypes.add(dep.type);
95 pkgJson[dep.type][dep.name] = dep.query;
96 }
97 for (const depType of depTypes) {
98 pkgJson[depType] = Object.fromEntries(sortBy__default["default"](Object.entries(pkgJson[depType]), ([key]) => key));
99 }
100 await fs__default["default"].writeJson(pkgPath, pkgJson, { spaces: 2 });
101 }
102 console.log();
103 console.log(`Running ${chalk__default["default"].blue("yarn install")} to install new versions`);
104 console.log();
105 await run.run("yarn", ["install"]);
106 }
107}
108const dependencies = createStepDefinition({
109 type: "dependencies",
110 deserialize() {
111 throw new Error("The dependency step may not be defined in JSON");
112 },
113 create(data) {
114 return new DependenciesStep(data);
115 }
116});
117
118class MessageStep {
119 constructor(data) {
120 this.data = data;
121 }
122 async run() {
123 console.log(this.data.message);
124 }
125}
126const message = createStepDefinition({
127 type: "message",
128 deserialize(obj) {
129 const { message: msg } = obj;
130 if (!msg || typeof msg !== "string" && !Array.isArray(msg)) {
131 throw new Error("Invalid install step, 'message' must be a string or array");
132 }
133 return new MessageStep({ message: [msg].flat().join("") });
134 },
135 create(data) {
136 return new MessageStep(data);
137 }
138});
139
140var stepDefinitionMap = /*#__PURE__*/Object.freeze({
141 __proto__: null,
142 appRoute: appRoute,
143 dependencies: dependencies,
144 message: message
145});
146
147const stepDefinitions = Object.values(stepDefinitionMap);
148async function fetchPluginPackage(id) {
149 const searchNames = [`@backstage/plugin-${id}`, `backstage-plugin-${id}`, id];
150 for (const name of searchNames) {
151 try {
152 const packageInfo = await packages.fetchPackageInfo(name);
153 return packageInfo;
154 } catch (error) {
155 if (error.name !== "NotFoundError") {
156 throw error;
157 }
158 }
159 }
160 throw new index.NotFoundError(`No matching package found for '${id}', tried ${searchNames.join(", ")}`);
161}
162class PluginInstaller {
163 constructor(steps) {
164 this.steps = steps;
165 }
166 static async resolveSteps(pkg, versionToInstall) {
167 var _a, _b;
168 const steps = [];
169 const dependencies$1 = [];
170 dependencies$1.push({
171 target: "packages/app",
172 type: "dependencies",
173 name: pkg.name,
174 query: versionToInstall || `^${pkg.version}`
175 });
176 steps.push({
177 type: "dependencies",
178 step: dependencies.create({ dependencies: dependencies$1 })
179 });
180 for (const step of (_b = (_a = pkg.experimentalInstallationRecipe) == null ? void 0 : _a.steps) != null ? _b : []) {
181 const { type } = step;
182 const definition = stepDefinitions.find((d) => d.type === type);
183 if (definition) {
184 steps.push({
185 type,
186 step: definition.deserialize(step, pkg)
187 });
188 } else {
189 throw new Error(`Unsupported step type: ${type}`);
190 }
191 }
192 return steps;
193 }
194 async run() {
195 for (const { type, step } of this.steps) {
196 console.log(`Running step ${type}`);
197 await step.run();
198 }
199 }
200}
201async function installPluginAndPeerPlugins(pkg) {
202 const pluginDeps = /* @__PURE__ */ new Map();
203 pluginDeps.set(pkg.name, { pkg });
204 await loadPeerPluginDeps(pkg, pluginDeps);
205 console.log(`Installing ${pkg.name} AND any peer plugin dependencies.`);
206 for (const [_pluginDepName, pluginDep] of pluginDeps.entries()) {
207 const { pkg: pluginDepPkg, versionToInstall } = pluginDep;
208 console.log(`Installing plugin: ${pluginDepPkg.name}: ${versionToInstall || pluginDepPkg.version}`);
209 const steps = await PluginInstaller.resolveSteps(pluginDepPkg, versionToInstall);
210 const installer = new PluginInstaller(steps);
211 await installer.run();
212 }
213}
214async function loadPackageJson(plugin) {
215 if (plugin.endsWith("package.json")) {
216 return await fs__default["default"].readJson(plugin);
217 }
218 return await fetchPluginPackage(plugin);
219}
220async function loadPeerPluginDeps(pkg, pluginMap) {
221 var _a, _b;
222 for (const [pluginId, pluginVersion] of Object.entries((_b = (_a = pkg.experimentalInstallationRecipe) == null ? void 0 : _a.peerPluginDependencies) != null ? _b : {})) {
223 const depPkg = await loadPackageJson(pluginId);
224 if (!pluginMap.get(depPkg.name)) {
225 pluginMap.set(depPkg.name, {
226 pkg: depPkg,
227 versionToInstall: pluginVersion
228 });
229 await loadPeerPluginDeps(depPkg, pluginMap);
230 }
231 }
232}
233var install = async (pluginId, cmd) => {
234 const from = pluginId || (cmd == null ? void 0 : cmd.from);
235 if (!from) {
236 throw new Error("Missing both <plugin-id> or a package.json file path in the --from flag.");
237 }
238 const pkg = await loadPackageJson(from);
239 await installPluginAndPeerPlugins(pkg);
240};
241
242exports["default"] = install;
243//# sourceMappingURL=install-96bdbee9.cjs.js.map