From 63877d53be791da6a2d9f408019afcf486b544bf Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Sat, 9 Nov 2024 20:33:53 +0100 Subject: [PATCH] Eject file command implementation --- src/bin/eject-file.ts | 68 +++++++++++++++++++ src/bin/main.ts | 33 +++++++++ ...etUiModuleFileSourceCodeReadyToBeCopied.ts | 11 +-- 3 files changed, 107 insertions(+), 5 deletions(-) create mode 100644 src/bin/eject-file.ts diff --git a/src/bin/eject-file.ts b/src/bin/eject-file.ts new file mode 100644 index 00000000..18d70ca9 --- /dev/null +++ b/src/bin/eject-file.ts @@ -0,0 +1,68 @@ +import type { BuildContext } from "./shared/buildContext"; +import { getUiModuleFileSourceCodeReadyToBeCopied } from "./postinstall/getUiModuleFileSourceCodeReadyToBeCopied"; +import { getAbsoluteAndInOsFormatPath } from "./tools/getAbsoluteAndInOsFormatPath"; +import { relative as pathRelative, dirname as pathDirname, join as pathJoin } from "path"; +import { getUiModuleMetas } from "./postinstall/uiModuleMeta"; +import { getInstalledModuleDirPath } from "./tools/getInstalledModuleDirPath"; +import * as fsPr from "fs/promises"; +import { + readManagedGitignoreFile, + writeManagedGitignoreFile +} from "./postinstall/managedGitignoreFile"; + +export async function command(params: { + buildContext: BuildContext; + cliCommandOptions: { + file: string; + }; +}) { + const { buildContext, cliCommandOptions } = params; + + const fileRelativePath = pathRelative( + buildContext.themeSrcDirPath, + getAbsoluteAndInOsFormatPath({ + cwd: buildContext.themeSrcDirPath, + pathIsh: cliCommandOptions.file + }) + ); + + const uiModuleMetas = await getUiModuleMetas({ buildContext }); + + const uiModuleMeta = uiModuleMetas.find(({ files }) => + files.map(({ fileRelativePath }) => fileRelativePath).includes(fileRelativePath) + ); + + if (!uiModuleMeta) { + throw new Error(`No UI module found for the file ${fileRelativePath}`); + } + + const uiModuleDirPath = await getInstalledModuleDirPath({ + moduleName: uiModuleMeta.moduleName, + packageJsonDirPath: pathDirname(buildContext.packageJsonFilePath), + projectDirPath: buildContext.projectDirPath + }); + + const sourceCode = await getUiModuleFileSourceCodeReadyToBeCopied({ + buildContext, + fileRelativePath, + isForEjection: true, + uiModuleName: uiModuleMeta.moduleName, + uiModuleDirPath, + uiModuleVersion: uiModuleMeta.version + }); + + await fsPr.writeFile( + pathJoin(buildContext.themeSrcDirPath, fileRelativePath), + sourceCode + ); + + const { ejectedFilesRelativePaths } = await readManagedGitignoreFile({ + buildContext + }); + + await writeManagedGitignoreFile({ + buildContext, + uiModuleMetas, + ejectedFilesRelativePaths: [...ejectedFilesRelativePaths, fileRelativePath] + }); +} diff --git a/src/bin/main.ts b/src/bin/main.ts index 15c73167..ff79adad 100644 --- a/src/bin/main.ts +++ b/src/bin/main.ts @@ -241,6 +241,39 @@ program } }); +program + .command<{ + file: string; + }>({ + name: "eject-file", + description: "Take ownership over a given file" + }) + .option({ + key: "file", + name: (() => { + const name = "file"; + + optionsKeys.push(name); + + return name; + })(), + description: [ + "Relative path of the file relative to the directory of your keycloak theme source", + "Example `--file src/login/page/Login.tsx`" + ].join(" ") + }) + .task({ + skip, + handler: async ({ projectDirPath, file }) => { + const { command } = await import("./eject-file"); + + await command({ + buildContext: getBuildContext({ projectDirPath }), + cliCommandOptions: { file } + }); + } + }); + // Fallback to build command if no command is provided { const [, , ...rest] = process.argv; diff --git a/src/bin/postinstall/getUiModuleFileSourceCodeReadyToBeCopied.ts b/src/bin/postinstall/getUiModuleFileSourceCodeReadyToBeCopied.ts index 6855c0b1..f6c47890 100644 --- a/src/bin/postinstall/getUiModuleFileSourceCodeReadyToBeCopied.ts +++ b/src/bin/postinstall/getUiModuleFileSourceCodeReadyToBeCopied.ts @@ -36,16 +36,17 @@ export async function getUiModuleFileSourceCodeReadyToBeCopied(params: { if (isForEjection) { return [ `/*`, - ` This file was ejected from ${uiModuleName} version ${uiModuleVersion}.`, + `This file was ejected from ${uiModuleName} version ${uiModuleVersion}.`, `*/` ].join("\n"); } else { return [ `/*`, - ` WARNING: Before modifying this file run the following command:`, - ` \`npx keycloakify eject-file ${fileRelativePath.split(pathSep).join("/")}\``, - ` `, - ` This file comes from ${uiModuleName} version ${uiModuleVersion}.`, + `WARNING: Before modifying this file run the following command:`, + ``, + `npx keycloakify eject-file --file ${fileRelativePath.split(pathSep).join("/")}\``, + ``, + `This file comes from ${uiModuleName} version ${uiModuleVersion}.`, `*/` ]; }