From 14fe55e5c4795a2f44b2c1aaf93153568c3ea851 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Thu, 16 May 2024 08:23:37 +0200 Subject: [PATCH] Factorize getBuildOptions --- .../shared/{buildOptions => }/buildOptions.ts | 99 ++++++++++++++++--- .../buildOptions/UserProvidedBuildOptions.ts | 21 ---- src/bin/shared/buildOptions/index.ts | 3 - .../shared/buildOptions/parsedPackageJson.ts | 32 ------ .../shared/buildOptions/resolvedViteConfig.ts | 41 -------- 5 files changed, 86 insertions(+), 110 deletions(-) rename src/bin/shared/{buildOptions => }/buildOptions.ts (65%) delete mode 100644 src/bin/shared/buildOptions/UserProvidedBuildOptions.ts delete mode 100644 src/bin/shared/buildOptions/index.ts delete mode 100644 src/bin/shared/buildOptions/parsedPackageJson.ts delete mode 100644 src/bin/shared/buildOptions/resolvedViteConfig.ts diff --git a/src/bin/shared/buildOptions/buildOptions.ts b/src/bin/shared/buildOptions.ts similarity index 65% rename from src/bin/shared/buildOptions/buildOptions.ts rename to src/bin/shared/buildOptions.ts index bfc4f7c8..ea3a9193 100644 --- a/src/bin/shared/buildOptions/buildOptions.ts +++ b/src/bin/shared/buildOptions.ts @@ -1,10 +1,13 @@ import { parse as urlParse } from "url"; -import { readParsedPackageJson } from "./parsedPackageJson"; import { join as pathJoin } from "path"; -import { getAbsoluteAndInOsFormatPath } from "../../tools/getAbsoluteAndInOsFormatPath"; -import { getResolvedViteConfig } from "./resolvedViteConfig"; -import { getNpmWorkspaceRootDirPath } from "../../tools/getNpmWorkspaceRootDirPath"; -import type { CliCommandOptions } from "../../main"; +import { getAbsoluteAndInOsFormatPath } from "../tools/getAbsoluteAndInOsFormatPath"; +import { getNpmWorkspaceRootDirPath } from "../tools/getNpmWorkspaceRootDirPath"; +import type { CliCommandOptions } from "../main"; +import { z } from "zod"; +import * as fs from "fs"; +import { assert } from "tsafe"; +import * as child_process from "child_process"; +import { vitePluginSubScriptEnvNames } from "./constants"; /** Consolidated build option gathered form CLI arguments and config in package.json */ export type BuildOptions = { @@ -30,6 +33,23 @@ export type BuildOptions = { npmWorkspaceRootDirPath: string; }; +export type UserProvidedBuildOptions = { + extraThemeProperties?: string[]; + artifactId?: string; + groupId?: string; + loginThemeResourcesFromKeycloakVersion?: string; + keycloakifyBuildDirPath?: string; + themeName?: string | string[]; +}; + +export type ResolvedViteConfig = { + buildDir: string; + publicDir: string; + assetsDir: string; + urlPathname: string | undefined; + userProvidedBuildOptions: UserProvidedBuildOptions; +}; + export function readBuildOptions(params: { cliCommandOptions: CliCommandOptions }): BuildOptions { const { cliCommandOptions } = params; @@ -44,14 +64,67 @@ export function readBuildOptions(params: { cliCommandOptions: CliCommandOptions }); })(); - const { resolvedViteConfig } = getResolvedViteConfig({ - reactAppRootDirPath - }); + const { resolvedViteConfig } = (() => { + if (fs.readdirSync(reactAppRootDirPath).find(fileBasename => fileBasename.startsWith("vite.config")) === undefined) { + return { "resolvedViteConfig": undefined }; + } - const { keycloakify: userProvidedBuildOptionsFromPackageJson, ...parsedPackageJson } = readParsedPackageJson({ reactAppRootDirPath }); + const output = child_process + .execSync("npx vite", { + "cwd": reactAppRootDirPath, + "env": { + ...process.env, + [vitePluginSubScriptEnvNames.resolveViteConfig]: "true" + } + }) + .toString("utf8"); - const userProvidedBuildOptions = { - ...userProvidedBuildOptionsFromPackageJson, + assert(output.includes(vitePluginSubScriptEnvNames.resolveViteConfig), "Seems like the Keycloakify's Vite plugin is not installed."); + + const resolvedViteConfigStr = output.split(vitePluginSubScriptEnvNames.resolveViteConfig).reverse()[0]; + + const resolvedViteConfig: ResolvedViteConfig = JSON.parse(resolvedViteConfigStr); + + return { resolvedViteConfig }; + })(); + + const parsedPackageJson = (() => { + type ParsedPackageJson = { + name: string; + version?: string; + homepage?: string; + keycloakify?: UserProvidedBuildOptions & { reactAppBuildDirPath?: string }; + }; + + const zParsedPackageJson = z.object({ + "name": z.string(), + "version": z.string().optional(), + "homepage": z.string().optional(), + "keycloakify": z + .object({ + "extraThemeProperties": z.array(z.string()).optional(), + "artifactId": z.string().optional(), + "groupId": z.string().optional(), + "loginThemeResourcesFromKeycloakVersion": z.string().optional(), + "reactAppBuildDirPath": z.string().optional(), + "keycloakifyBuildDirPath": z.string().optional(), + "themeName": z.union([z.string(), z.array(z.string())]).optional() + }) + .optional() + }); + + { + type Got = ReturnType<(typeof zParsedPackageJson)["parse"]>; + type Expected = ParsedPackageJson; + assert(); + assert(); + } + + return zParsedPackageJson.parse(JSON.parse(fs.readFileSync(pathJoin(reactAppRootDirPath, "package.json")).toString("utf8"))); + })(); + + const userProvidedBuildOptions: UserProvidedBuildOptions = { + ...parsedPackageJson.keycloakify, ...resolvedViteConfig?.userProvidedBuildOptions }; @@ -78,9 +151,9 @@ export function readBuildOptions(params: { cliCommandOptions: CliCommandOptions break webpack; } - if (userProvidedBuildOptions.reactAppBuildDirPath !== undefined) { + if (parsedPackageJson.keycloakify?.reactAppBuildDirPath !== undefined) { return getAbsoluteAndInOsFormatPath({ - "pathIsh": userProvidedBuildOptions.reactAppBuildDirPath, + "pathIsh": parsedPackageJson.keycloakify.reactAppBuildDirPath, "cwd": reactAppRootDirPath }); } diff --git a/src/bin/shared/buildOptions/UserProvidedBuildOptions.ts b/src/bin/shared/buildOptions/UserProvidedBuildOptions.ts deleted file mode 100644 index 167e7d0a..00000000 --- a/src/bin/shared/buildOptions/UserProvidedBuildOptions.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { z } from "zod"; - -export type UserProvidedBuildOptions = { - extraThemeProperties?: string[]; - artifactId?: string; - groupId?: string; - loginThemeResourcesFromKeycloakVersion?: string; - reactAppBuildDirPath?: string; - keycloakifyBuildDirPath?: string; - themeName?: string | string[]; -}; - -export const zUserProvidedBuildOptions = z.object({ - "extraThemeProperties": z.array(z.string()).optional(), - "artifactId": z.string().optional(), - "groupId": z.string().optional(), - "loginThemeResourcesFromKeycloakVersion": z.string().optional(), - "reactAppBuildDirPath": z.string().optional(), - "keycloakifyBuildDirPath": z.string().optional(), - "themeName": z.union([z.string(), z.array(z.string())]).optional() -}); diff --git a/src/bin/shared/buildOptions/index.ts b/src/bin/shared/buildOptions/index.ts deleted file mode 100644 index 2ff4cfd4..00000000 --- a/src/bin/shared/buildOptions/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./buildOptions"; -export type { UserProvidedBuildOptions } from "./UserProvidedBuildOptions"; -export type { ResolvedViteConfig } from "./resolvedViteConfig"; diff --git a/src/bin/shared/buildOptions/parsedPackageJson.ts b/src/bin/shared/buildOptions/parsedPackageJson.ts deleted file mode 100644 index a0ce604c..00000000 --- a/src/bin/shared/buildOptions/parsedPackageJson.ts +++ /dev/null @@ -1,32 +0,0 @@ -import * as fs from "fs"; -import { assert } from "tsafe"; -import type { Equals } from "tsafe"; -import { z } from "zod"; -import { join as pathJoin } from "path"; -import { type UserProvidedBuildOptions, zUserProvidedBuildOptions } from "./UserProvidedBuildOptions"; - -export type ParsedPackageJson = { - name: string; - version?: string; - homepage?: string; - keycloakify?: UserProvidedBuildOptions; -}; - -const zParsedPackageJson = z.object({ - "name": z.string(), - "version": z.string().optional(), - "homepage": z.string().optional(), - "keycloakify": zUserProvidedBuildOptions.optional() -}); - -assert, ParsedPackageJson>>(); - -let parsedPackageJson: undefined | ParsedPackageJson; -export function readParsedPackageJson(params: { reactAppRootDirPath: string }) { - const { reactAppRootDirPath } = params; - if (parsedPackageJson) { - return parsedPackageJson; - } - parsedPackageJson = zParsedPackageJson.parse(JSON.parse(fs.readFileSync(pathJoin(reactAppRootDirPath, "package.json")).toString("utf8"))); - return parsedPackageJson; -} diff --git a/src/bin/shared/buildOptions/resolvedViteConfig.ts b/src/bin/shared/buildOptions/resolvedViteConfig.ts deleted file mode 100644 index a1f334bb..00000000 --- a/src/bin/shared/buildOptions/resolvedViteConfig.ts +++ /dev/null @@ -1,41 +0,0 @@ -import * as fs from "fs"; -import { UserProvidedBuildOptions } from "./UserProvidedBuildOptions"; -import * as child_process from "child_process"; -import { vitePluginSubScriptEnvNames } from "../constants"; -import { assert } from "tsafe/assert"; - -export type ResolvedViteConfig = { - buildDir: string; - publicDir: string; - assetsDir: string; - urlPathname: string | undefined; - userProvidedBuildOptions: UserProvidedBuildOptions; -}; - -export function getResolvedViteConfig(params: { reactAppRootDirPath: string }): { - resolvedViteConfig: ResolvedViteConfig | undefined; -} { - const { reactAppRootDirPath } = params; - - if (fs.readdirSync(reactAppRootDirPath).find(fileBasename => fileBasename.startsWith("vite.config")) === undefined) { - return { "resolvedViteConfig": undefined }; - } - - const output = child_process - .execSync("npx vite", { - "cwd": reactAppRootDirPath, - "env": { - ...process.env, - [vitePluginSubScriptEnvNames.resolveViteConfig]: "true" - } - }) - .toString("utf8"); - - assert(output.includes(vitePluginSubScriptEnvNames.resolveViteConfig), "Seems like the Keycloakify's Vite plugin is not installed."); - - const resolvedViteConfigStr = output.split(vitePluginSubScriptEnvNames.resolveViteConfig).reverse()[0]; - - const resolvedViteConfig: ResolvedViteConfig = JSON.parse(resolvedViteConfigStr); - - return { resolvedViteConfig }; -}