From 2176d33da10c007069900a41beda5cdbf477a8c4 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Sat, 24 Feb 2024 05:08:39 +0100 Subject: [PATCH] Support generating source map --- package.json | 3 +- src/vite-plugin/vite-plugin.ts | 80 +++++++++++++++++++--------------- yarn.lock | 9 +++- 3 files changed, 54 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index 6b9f1be8..af173d29 100644 --- a/package.json +++ b/package.json @@ -125,6 +125,7 @@ "tsafe": "^1.6.0", "yauzl": "^2.10.0", "yazl": "^2.5.1", - "zod": "^3.17.10" + "zod": "^3.17.10", + "magic-string": "^0.30.7" } } diff --git a/src/vite-plugin/vite-plugin.ts b/src/vite-plugin/vite-plugin.ts index ab65b81a..43ad5495 100644 --- a/src/vite-plugin/vite-plugin.ts +++ b/src/vite-plugin/vite-plugin.ts @@ -10,13 +10,13 @@ import { } from "../bin/constants"; import type { ResolvedViteConfig } from "../bin/keycloakify/buildOptions/resolvedViteConfig"; import { getCacheDirPath } from "../bin/keycloakify/buildOptions/getCacheDirPath"; -import { replaceAll } from "../bin/tools/String.prototype.replaceAll"; import { id } from "tsafe/id"; import { rm } from "../bin/tools/fs.rm"; import { copyKeycloakResourcesToPublic } from "../bin/copy-keycloak-resources-to-public"; import { assert } from "tsafe/assert"; import type { BuildOptions } from "../bin/keycloakify/buildOptions"; import type { UserProvidedBuildOptions } from "../bin/keycloakify/buildOptions/UserProvidedBuildOptions"; +import MagicString from "magic-string"; export type Params = UserProvidedBuildOptions & { postBuild?: (buildOptions: Omit) => Promise; @@ -29,10 +29,13 @@ export function keycloakify(params?: Params) { let urlPathname: string | undefined = undefined; let buildDirPath: string | undefined = undefined; let command: "build" | "serve" | undefined = undefined; + let shouldGenerateSourcemap: boolean | undefined = undefined; const plugin = { "name": "keycloakify" as const, "configResolved": async resolvedConfig => { + shouldGenerateSourcemap = resolvedConfig.build.sourcemap !== false; + run_post_build_script: { const buildOptionJson = process.env[keycloakifyBuildOptionsForPostPostBuildScriptEnvName]; @@ -115,6 +118,7 @@ export function keycloakify(params?: Params) { }, "transform": (code, id) => { assert(command !== undefined); + assert(shouldGenerateSourcemap !== undefined); if (command !== "build") { return; @@ -122,49 +126,53 @@ export function keycloakify(params?: Params) { assert(reactAppRootDirPath !== undefined); - let transformedCode: string | undefined = undefined; + { + const isWithinSourceDirectory = id.startsWith(pathJoin(reactAppRootDirPath, "src") + pathSep); - replace_import_meta_env_base_url_in_source_code: { - { - const isWithinSourceDirectory = id.startsWith(pathJoin(reactAppRootDirPath, "src") + pathSep); - - if (!isWithinSourceDirectory) { - break replace_import_meta_env_base_url_in_source_code; - } + if (!isWithinSourceDirectory) { + return; } - - { - const isJavascriptFile = id.endsWith(".js") || id.endsWith(".jsx"); - const isTypeScriptFile = id.endsWith(".ts") || id.endsWith(".tsx"); - - if (!isTypeScriptFile && !isJavascriptFile) { - break replace_import_meta_env_base_url_in_source_code; - } - } - - if (transformedCode === undefined) { - transformedCode = code; - } - - transformedCode = replaceAll( - transformedCode, - "import.meta.env.BASE_URL", - [ - `(`, - `(window.${nameOfTheGlobal} === undefined || import.meta.env.MODE === "development")?`, - `"${urlPathname ?? "/"}":`, - `(window.${nameOfTheGlobal}.url.resourcesPath + "/${basenameOfTheKeycloakifyResourcesDir}/")`, - `)` - ].join("") - ); } - if (transformedCode === undefined) { + { + const isJavascriptFile = id.endsWith(".js") || id.endsWith(".jsx"); + const isTypeScriptFile = id.endsWith(".ts") || id.endsWith(".tsx"); + + if (!isTypeScriptFile && !isJavascriptFile) { + return; + } + } + + const transformedCode = new MagicString(code); + + transformedCode.replaceAll( + /import\.meta\.env(?:(?:\.BASE_URL)|(?:\["BASE_URL"\]))/g, + [ + `(`, + `(window.${nameOfTheGlobal} === undefined || import.meta.env.MODE === "development")?`, + `"${urlPathname ?? "/"}":`, + `(window.${nameOfTheGlobal}.url.resourcesPath + "/${basenameOfTheKeycloakifyResourcesDir}/")`, + `)` + ].join("") + ); + + if (!transformedCode.hasChanged()) { return; } + if (!shouldGenerateSourcemap) { + return transformedCode.toString(); + } + + const map = transformedCode.generateMap({ + "source": id, + "includeContent": true, + "hires": true + }); + return { - "code": transformedCode + "code": transformedCode.toString(), + "map": map.toString() }; }, "closeBundle": async () => { diff --git a/yarn.lock b/yarn.lock index 9e512cc1..48105dad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1665,7 +1665,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== -"@jridgewell/sourcemap-codec@^1.4.10": +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.15": version "1.4.15" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== @@ -8352,6 +8352,13 @@ lz-string@^1.4.4: resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== +magic-string@^0.30.7: + version "0.30.7" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.7.tgz#0cecd0527d473298679da95a2d7aeb8c64048505" + integrity sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.15" + make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"