Skip to content

Commit

Permalink
feat(cli-plugin-scaffold-extensions): add link-extensions command
Browse files Browse the repository at this point in the history
  • Loading branch information
Pavel910 committed Jun 20, 2024
1 parent 8c7f12e commit aa8dbfb
Show file tree
Hide file tree
Showing 11 changed files with 338 additions and 171 deletions.
9 changes: 9 additions & 0 deletions packages/cli-plugin-scaffold-extensions/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const defaultConfig = require("../../.eslintrc");

module.exports = {
...defaultConfig,
rules: {
...defaultConfig.rules,
"import/dynamic-import-chunkname": 0
}
};
1 change: 1 addition & 0 deletions packages/cli-plugin-scaffold-extensions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@webiny/error": "0.0.0",
"case": "^1.6.3",
"execa": "^5.0.0",
"glob": "^7.1.2",
"load-json-file": "^6.2.0",
"ncp": "^2.0.0",
"replace-in-path": "^1.1.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import fs from "fs";
import path from "path";
import { formatCode } from "@webiny/cli-plugin-scaffold/utils";
import { ExtensionWorkspace } from "./getExtensionsFromFilesystem";

export const generateAdminExtensions = async (extensions: ExtensionWorkspace[]) => {
const extensionsFilePath = path.join("apps", "admin", "src", "Extensions.tsx");

const code: string[][] = [];

extensions.forEach(extension => {
const name = path.basename(extension.path);
const ucFirstName = name.charAt(0).toUpperCase() + name.slice(1);
const componentName = ucFirstName + "Extension";
const importStatement = `import { Extension as ${componentName}} from "${extension.packageJson.name}";`;
code.push([importStatement, `<${componentName}/>`]);
});

const extensionsFile = [
`// This file is automatically updated via scaffolding utilities.`,
`import React from "react";`,
...code.map(ext => ext[0]),
"",
`export const Extensions = () => { return (<>${code.map(ext => ext[1]).join("\n")}</>); };`
];

fs.writeFileSync(extensionsFilePath, extensionsFile.join("\n"));

await formatCode(extensionsFilePath, {});
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import fs from "fs";
import path from "path";
import { formatCode } from "@webiny/cli-plugin-scaffold/utils";
import { ExtensionWorkspace } from "./getExtensionsFromFilesystem";

export const generateApiExtensions = async (extensions: ExtensionWorkspace[]) => {
const extensionsFilePath = path.join("apps", "api", "graphql", "src", "extensions.ts");
const code: string[][] = [];

extensions.forEach(extension => {
const name = path.basename(extension.path);
const extensionFactory = name + "ExtensionFactory";
const importStatement = `import { createExtension as ${extensionFactory}} from "${extension.packageJson.name}";`;
code.push([importStatement, `${extensionFactory}()`]);
});

const extensionsFile = [
"// This file is automatically updated via scaffolding utilities.",
...code.map(ext => ext[0]),
"export const extensions = () => {",
"return [",
code.map(ext => ext[1]).join(","),
"];};"
];

fs.writeFileSync(extensionsFilePath, extensionsFile.join("\n"));

await formatCode(extensionsFilePath, {});
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import loadJson from "load-json-file";
import glob from "glob";
import path from "path";
import { PackageJson } from "@webiny/cli-plugin-scaffold/types";

export type ExtensionType = "api" | "admin" | undefined;

export type ExtensionWorkspace = {
path: string;
type: ExtensionType;
packageJson: PackageJson;
};

export const getExtensionsFromFilesystem = (): ExtensionWorkspace[] => {
const workspaces = glob.sync(`extensions/**/package.json`);
return workspaces
.map(pkg => ({
path: path.dirname(pkg),
packageJson: loadJson.sync<PackageJson>(pkg)
}))
.map(workspace => {
const typeKeyword = (workspace.packageJson.keywords || []).find(kw => {
return kw.startsWith("webiny-extension-type:");
});

const type = (typeKeyword ? typeKeyword.split(":")[1] : undefined) as ExtensionType;

return {
...workspace,
type
};
});
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { getExtensionsFromFilesystem } from "./getExtensionsFromFilesystem";
import { generateApiExtensions } from "./generateApiExtensions";
import { generateAdminExtensions } from "./generateAdminExtensions";
import { registerWorkspaces } from "./registerWorkspaces";

export const linkAllExtensions = async () => {
const allExtensions = getExtensionsFromFilesystem();
const apiExtensions = allExtensions.filter(extension => extension.type === "api");
const adminExtensions = allExtensions.filter(extension => extension.type === "admin");

await Promise.all([
generateApiExtensions(apiExtensions),
generateAdminExtensions(adminExtensions),
registerWorkspaces(allExtensions)
]);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import execa from "execa";
import loadJson from "load-json-file";
import writeJson from "write-json-file";
import type { ExtensionWorkspace } from "./getExtensionsFromFilesystem";
import { PackageJson } from "@webiny/cli-plugin-scaffold/types";
import { formatCode } from "@webiny/cli-plugin-scaffold/utils";

export const registerWorkspaces = async (extensions: ExtensionWorkspace[]) => {
const packageJsonPath = "package.json";
const rootPkgJson = await loadJson<PackageJson>(packageJsonPath);

extensions.forEach(extension => {
const workspacePath = extension.path.replace(`${process.cwd()}/`, "");

if (!rootPkgJson.workspaces.packages.includes(workspacePath)) {
rootPkgJson.workspaces.packages.push(workspacePath);
}
});

await writeJson(packageJsonPath, rootPkgJson);
await formatCode(packageJsonPath, {});

await execa("yarn");
};
Loading

0 comments on commit aa8dbfb

Please sign in to comment.