diff --git a/src/bin/update-kc-gen.ts b/src/bin/update-kc-gen.ts index 2c758458..985b3710 100644 --- a/src/bin/update-kc-gen.ts +++ b/src/bin/update-kc-gen.ts @@ -4,6 +4,7 @@ import { join as pathJoin } from "path"; import { existsAsync } from "./tools/fs.existsAsync"; import { maybeDelegateCommandToCustomHandler } from "./shared/customHandler_delegate"; import { runFormat } from "./tools/runFormat"; +import * as crypto from "crypto"; export async function command(params: { buildContext: BuildContext }) { const { buildContext } = params; @@ -19,86 +20,106 @@ export async function command(params: { buildContext: BuildContext }) { const filePath = pathJoin(buildContext.themeSrcDirPath, `kc.gen.tsx`); - const currentContent = (await existsAsync(filePath)) - ? await fs.readFile(filePath) - : undefined; - const hasLoginTheme = buildContext.implementedThemeTypes.login.isImplemented; const hasAccountTheme = buildContext.implementedThemeTypes.account.isImplemented; - const newContent = Buffer.from( - [ - ``, - `// This file is auto-generated by Keycloakify, do not modify it manually.`, - ``, - `import { lazy, Suspense, type ReactNode } from "react";`, - ``, - `export type ThemeName = ${buildContext.themeNames.map(themeName => `"${themeName}"`).join(" | ")};`, - ``, - `export const themeNames: ThemeName[] = [${buildContext.themeNames.map(themeName => `"${themeName}"`).join(", ")}];`, - ``, - `export type KcEnvName = ${buildContext.environmentVariables.length === 0 ? "never" : buildContext.environmentVariables.map(({ name }) => `"${name}"`).join(" | ")};`, - ``, - `export const kcEnvNames: KcEnvName[] = [${buildContext.environmentVariables.map(({ name }) => `"${name}"`).join(", ")}];`, - ``, - `export const kcEnvDefaults: Record = ${JSON.stringify( - Object.fromEntries( - buildContext.environmentVariables.map( - ({ name, default: defaultValue }) => [name, defaultValue] - ) - ), - null, - 2 - )};`, - ``, - `export type KcContext =`, - hasLoginTheme && ` | import("./login/KcContext").KcContext`, - hasAccountTheme && ` | import("./account/KcContext").KcContext`, - ` ;`, - ``, - `declare global {`, - ` interface Window {`, - ` kcContext?: KcContext;`, - ` }`, - `}`, - ``, - hasLoginTheme && - `export const KcLoginPage = lazy(() => import("./login/KcPage"));`, - hasAccountTheme && - `export const KcAccountPage = lazy(() => import("./account/KcPage"));`, - ``, - `export function KcPage(`, - ` props: {`, - ` kcContext: KcContext;`, - ` fallback?: ReactNode;`, - ` }`, - `) {`, - ` const { kcContext, fallback } = props;`, - ` return (`, - ` `, - ` {(() => {`, - ` switch (kcContext.themeType) {`, - hasLoginTheme && - ` case "login": return ;`, - hasAccountTheme && - ` case "account": return ;`, - ` }`, - ` })()}`, - ` `, - ` );`, - `}`, - `` - ] - .filter(item => typeof item === "string") - .join("\n"), - "utf8" - ); + const newContent = [ + ``, + `/* eslint-disable */`, + ``, + `// @ts-nocheck`, + ``, + `// noinspection JSUnusedGlobalSymbols`, + ``, + `import { lazy, Suspense, type ReactNode } from "react";`, + ``, + `export type ThemeName = ${buildContext.themeNames.map(themeName => `"${themeName}"`).join(" | ")};`, + ``, + `export const themeNames: ThemeName[] = [${buildContext.themeNames.map(themeName => `"${themeName}"`).join(", ")}];`, + ``, + `export type KcEnvName = ${buildContext.environmentVariables.length === 0 ? "never" : buildContext.environmentVariables.map(({ name }) => `"${name}"`).join(" | ")};`, + ``, + `export const kcEnvNames: KcEnvName[] = [${buildContext.environmentVariables.map(({ name }) => `"${name}"`).join(", ")}];`, + ``, + `export const kcEnvDefaults: Record = ${JSON.stringify( + Object.fromEntries( + buildContext.environmentVariables.map( + ({ name, default: defaultValue }) => [name, defaultValue] + ) + ), + null, + 2 + )};`, + ``, + `export type KcContext =`, + hasLoginTheme && ` | import("./login/KcContext").KcContext`, + hasAccountTheme && ` | import("./account/KcContext").KcContext`, + ` ;`, + ``, + `declare global {`, + ` interface Window {`, + ` kcContext?: KcContext;`, + ` }`, + `}`, + ``, + hasLoginTheme && + `export const KcLoginPage = lazy(() => import("./login/KcPage"));`, + hasAccountTheme && + `export const KcAccountPage = lazy(() => import("./account/KcPage"));`, + ``, + `export function KcPage(`, + ` props: {`, + ` kcContext: KcContext;`, + ` fallback?: ReactNode;`, + ` }`, + `) {`, + ` const { kcContext, fallback } = props;`, + ` return (`, + ` `, + ` {(() => {`, + ` switch (kcContext.themeType) {`, + hasLoginTheme && + ` case "login": return ;`, + hasAccountTheme && + ` case "account": return ;`, + ` }`, + ` })()}`, + ` `, + ` );`, + `}`, + `` + ] + .filter(item => typeof item === "string") + .join("\n"); + + const hash = crypto.createHash("sha256").update(newContent).digest("hex"); + + skip_if_no_changes: { + if (!(await existsAsync(filePath))) { + break skip_if_no_changes; + } + + const currentContent = (await fs.readFile(filePath)).toString("utf8"); + + if (!currentContent.includes(hash)) { + break skip_if_no_changes; + } - if (currentContent !== undefined && currentContent.equals(newContent)) { return; } - await fs.writeFile(filePath, newContent); + await fs.writeFile( + filePath, + Buffer.from( + [ + `// This file is auto-generated by the \`update-kc-gen\` command. Do not edit it manually.`, + `// Hash: ${hash}`, + ``, + newContent + ].join("\n"), + "utf8" + ) + ); runFormat({ packageJsonFilePath: buildContext.packageJsonFilePath });