Remove --external-assets option
This commit is contained in:
parent
641cc38ae4
commit
1c25b69160
@ -15,6 +15,7 @@ export async function downloadBuiltinKeycloakTheme(params: { projectDirPath: str
|
|||||||
console.log("Downloading Keycloak theme...", { keycloakVersion });
|
console.log("Downloading Keycloak theme...", { keycloakVersion });
|
||||||
|
|
||||||
await downloadAndUnzip({
|
await downloadAndUnzip({
|
||||||
|
"doUseCache": true,
|
||||||
projectDirPath,
|
projectDirPath,
|
||||||
destDirPath,
|
destDirPath,
|
||||||
"url": `https://github.com/keycloak/keycloak/archive/refs/tags/${keycloakVersion}.zip`,
|
"url": `https://github.com/keycloak/keycloak/archive/refs/tags/${keycloakVersion}.zip`,
|
||||||
|
@ -4,15 +4,11 @@ import { parse as urlParse } from "url";
|
|||||||
import { typeGuard } from "tsafe/typeGuard";
|
import { typeGuard } from "tsafe/typeGuard";
|
||||||
import { symToStr } from "tsafe/symToStr";
|
import { symToStr } from "tsafe/symToStr";
|
||||||
import { bundlers, getParsedPackageJson, type Bundler } from "./parsedPackageJson";
|
import { bundlers, getParsedPackageJson, type Bundler } from "./parsedPackageJson";
|
||||||
import * as fs from "fs";
|
|
||||||
import { join as pathJoin, sep as pathSep } from "path";
|
import { join as pathJoin, sep as pathSep } from "path";
|
||||||
import parseArgv from "minimist";
|
import parseArgv from "minimist";
|
||||||
|
|
||||||
/** Consolidated build option gathered form CLI arguments and config in package.json */
|
/** Consolidated build option gathered form CLI arguments and config in package.json */
|
||||||
export type BuildOptions = BuildOptions.Standalone | BuildOptions.ExternalAssets;
|
export type BuildOptions = {
|
||||||
|
|
||||||
export namespace BuildOptions {
|
|
||||||
export type Common = {
|
|
||||||
isSilent: boolean;
|
isSilent: boolean;
|
||||||
themeVersion: string;
|
themeVersion: string;
|
||||||
themeName: string;
|
themeName: string;
|
||||||
@ -26,84 +22,24 @@ export namespace BuildOptions {
|
|||||||
reactAppBuildDirPath: string;
|
reactAppBuildDirPath: string;
|
||||||
/** Directory that keycloakify outputs to. Defaults to {cwd}/build_keycloak */
|
/** Directory that keycloakify outputs to. Defaults to {cwd}/build_keycloak */
|
||||||
keycloakifyBuildDirPath: string;
|
keycloakifyBuildDirPath: string;
|
||||||
};
|
/** If your app is hosted under a subpath, it's the case in CRA if you have "homepage": "https://example.com/my-app" in your package.json
|
||||||
|
* In this case the urlPathname will be "/my-app/" */
|
||||||
export type Standalone = Common & {
|
|
||||||
isStandalone: true;
|
|
||||||
urlPathname: string | undefined;
|
urlPathname: string | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ExternalAssets = ExternalAssets.SameDomain | ExternalAssets.DifferentDomains;
|
|
||||||
|
|
||||||
export namespace ExternalAssets {
|
|
||||||
export type CommonExternalAssets = Common & {
|
|
||||||
isStandalone: false;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type SameDomain = CommonExternalAssets & {
|
|
||||||
areAppAndKeycloakServerSharingSameDomain: true;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type DifferentDomains = CommonExternalAssets & {
|
|
||||||
areAppAndKeycloakServerSharingSameDomain: false;
|
|
||||||
urlOrigin: string;
|
|
||||||
urlPathname: string | undefined;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function readBuildOptions(params: { projectDirPath: string; processArgv: string[] }): BuildOptions {
|
export function readBuildOptions(params: { projectDirPath: string; processArgv: string[] }): BuildOptions {
|
||||||
const { projectDirPath, processArgv } = params;
|
const { projectDirPath, processArgv } = params;
|
||||||
|
|
||||||
const { isExternalAssetsCliParamProvided, isSilentCliParamProvided } = (() => {
|
const { isSilentCliParamProvided } = (() => {
|
||||||
const argv = parseArgv(processArgv);
|
const argv = parseArgv(processArgv);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"isSilentCliParamProvided": typeof argv["silent"] === "boolean" ? argv["silent"] : false,
|
"isSilentCliParamProvided": typeof argv["silent"] === "boolean" ? argv["silent"] : false
|
||||||
"isExternalAssetsCliParamProvided": typeof argv["external-assets"] === "boolean" ? argv["external-assets"] : false
|
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const parsedPackageJson = getParsedPackageJson({ projectDirPath });
|
const parsedPackageJson = getParsedPackageJson({ projectDirPath });
|
||||||
|
|
||||||
const url = (() => {
|
|
||||||
const { homepage } = parsedPackageJson;
|
|
||||||
|
|
||||||
let url: URL | undefined = undefined;
|
|
||||||
|
|
||||||
if (homepage !== undefined) {
|
|
||||||
url = new URL(homepage);
|
|
||||||
}
|
|
||||||
|
|
||||||
const CNAME = (() => {
|
|
||||||
const cnameFilePath = pathJoin(projectDirPath, "public", "CNAME");
|
|
||||||
|
|
||||||
if (!fs.existsSync(cnameFilePath)) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fs.readFileSync(cnameFilePath).toString("utf8");
|
|
||||||
})();
|
|
||||||
|
|
||||||
if (CNAME !== undefined) {
|
|
||||||
url = new URL(`https://${CNAME.replace(/\s+$/, "")}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (url === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
"origin": url.origin,
|
|
||||||
"pathname": (() => {
|
|
||||||
const out = url.pathname.replace(/([^/])$/, "$1/");
|
|
||||||
|
|
||||||
return out === "/" ? undefined : out;
|
|
||||||
})()
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|
||||||
const common: BuildOptions.Common = (() => {
|
|
||||||
const { name, keycloakify = {}, version, homepage } = parsedPackageJson;
|
const { name, keycloakify = {}, version, homepage } = parsedPackageJson;
|
||||||
|
|
||||||
const { extraThemeProperties, groupId, artifactId, bundler, keycloakVersionDefaultAssets, extraThemeNames = [] } = keycloakify ?? {};
|
const { extraThemeProperties, groupId, artifactId, bundler, keycloakVersionDefaultAssets, extraThemeNames = [] } = keycloakify ?? {};
|
||||||
@ -122,10 +58,7 @@ export function readBuildOptions(params: { projectDirPath: string; processArgv:
|
|||||||
const { KEYCLOAKIFY_BUNDLER } = process.env;
|
const { KEYCLOAKIFY_BUNDLER } = process.env;
|
||||||
|
|
||||||
assert(
|
assert(
|
||||||
typeGuard<Bundler | undefined>(
|
typeGuard<Bundler | undefined>(KEYCLOAKIFY_BUNDLER, [undefined, ...id<readonly string[]>(bundlers)].includes(KEYCLOAKIFY_BUNDLER)),
|
||||||
KEYCLOAKIFY_BUNDLER,
|
|
||||||
[undefined, ...id<readonly string[]>(bundlers)].includes(KEYCLOAKIFY_BUNDLER)
|
|
||||||
),
|
|
||||||
`${symToStr({ KEYCLOAKIFY_BUNDLER })} should be one of ${bundlers.join(", ")}`
|
`${symToStr({ KEYCLOAKIFY_BUNDLER })} should be one of ${bundlers.join(", ")}`
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -184,48 +117,22 @@ export function readBuildOptions(params: { projectDirPath: string; processArgv:
|
|||||||
}
|
}
|
||||||
|
|
||||||
return keycloakifyBuildDirPath;
|
return keycloakifyBuildDirPath;
|
||||||
|
})(),
|
||||||
|
"urlPathname": (() => {
|
||||||
|
const { homepage } = parsedPackageJson;
|
||||||
|
|
||||||
|
let url: URL | undefined = undefined;
|
||||||
|
|
||||||
|
if (homepage !== undefined) {
|
||||||
|
url = new URL(homepage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const out = url.pathname.replace(/([^/])$/, "$1/");
|
||||||
|
return out === "/" ? undefined : out;
|
||||||
})()
|
})()
|
||||||
};
|
};
|
||||||
})();
|
|
||||||
|
|
||||||
if (isExternalAssetsCliParamProvided) {
|
|
||||||
const commonExternalAssets = id<BuildOptions.ExternalAssets.CommonExternalAssets>({
|
|
||||||
...common,
|
|
||||||
"isStandalone": false
|
|
||||||
});
|
|
||||||
|
|
||||||
if (parsedPackageJson.keycloakify?.areAppAndKeycloakServerSharingSameDomain) {
|
|
||||||
return id<BuildOptions.ExternalAssets.SameDomain>({
|
|
||||||
...commonExternalAssets,
|
|
||||||
"areAppAndKeycloakServerSharingSameDomain": true
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
assert(
|
|
||||||
url !== undefined,
|
|
||||||
[
|
|
||||||
"Can't compile in external assets mode if we don't know where",
|
|
||||||
"the app will be hosted.",
|
|
||||||
"You should provide a homepage field in the package.json (or create a",
|
|
||||||
"public/CNAME file.",
|
|
||||||
"Alternatively, if your app and the Keycloak server are on the same domain, ",
|
|
||||||
"eg https://example.com is your app and https://example.com/auth is the keycloak",
|
|
||||||
'admin UI, you can set "keycloakify": { "areAppAndKeycloakServerSharingSameDomain": true }',
|
|
||||||
"in your package.json"
|
|
||||||
].join(" ")
|
|
||||||
);
|
|
||||||
|
|
||||||
return id<BuildOptions.ExternalAssets.DifferentDomains>({
|
|
||||||
...commonExternalAssets,
|
|
||||||
"areAppAndKeycloakServerSharingSameDomain": false,
|
|
||||||
"urlOrigin": url.origin,
|
|
||||||
"urlPathname": url.pathname
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return id<BuildOptions.Standalone>({
|
|
||||||
...common,
|
|
||||||
"isStandalone": true,
|
|
||||||
"urlPathname": url?.pathname
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
@ -13,39 +13,11 @@ export const themeTypes = ["login", "account"] as const;
|
|||||||
|
|
||||||
export type ThemeType = (typeof themeTypes)[number];
|
export type ThemeType = (typeof themeTypes)[number];
|
||||||
|
|
||||||
export type BuildOptionsLike = BuildOptionsLike.Standalone | BuildOptionsLike.ExternalAssets;
|
export type BuildOptionsLike = {
|
||||||
|
|
||||||
export namespace BuildOptionsLike {
|
|
||||||
export type Common = {
|
|
||||||
themeName: string;
|
themeName: string;
|
||||||
themeVersion: string;
|
themeVersion: string;
|
||||||
};
|
|
||||||
|
|
||||||
export type Standalone = Common & {
|
|
||||||
isStandalone: true;
|
|
||||||
urlPathname: string | undefined;
|
urlPathname: string | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ExternalAssets = ExternalAssets.SameDomain | ExternalAssets.DifferentDomains;
|
|
||||||
|
|
||||||
export namespace ExternalAssets {
|
|
||||||
export type CommonExternalAssets = {
|
|
||||||
isStandalone: false;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type SameDomain = Common &
|
|
||||||
CommonExternalAssets & {
|
|
||||||
areAppAndKeycloakServerSharingSameDomain: true;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type DifferentDomains = Common &
|
|
||||||
CommonExternalAssets & {
|
|
||||||
areAppAndKeycloakServerSharingSameDomain: false;
|
|
||||||
urlOrigin: string;
|
|
||||||
urlPathname: string | undefined;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert<BuildOptions extends BuildOptionsLike ? true : false>();
|
assert<BuildOptions extends BuildOptionsLike ? true : false>();
|
||||||
|
|
||||||
@ -63,22 +35,23 @@ export function generateFtlFilesCodeFactory(params: {
|
|||||||
const $ = cheerio.load(indexHtmlCode);
|
const $ = cheerio.load(indexHtmlCode);
|
||||||
|
|
||||||
fix_imports_statements: {
|
fix_imports_statements: {
|
||||||
if (!buildOptions.isStandalone && buildOptions.areAppAndKeycloakServerSharingSameDomain) {
|
|
||||||
break fix_imports_statements;
|
|
||||||
}
|
|
||||||
|
|
||||||
$("script:not([src])").each((...[, element]) => {
|
$("script:not([src])").each((...[, element]) => {
|
||||||
const { fixedJsCode } = replaceImportsFromStaticInJsCode({
|
const jsCode = $(element).html();
|
||||||
"jsCode": $(element).html()!,
|
|
||||||
buildOptions
|
assert(jsCode !== null);
|
||||||
});
|
|
||||||
|
const { fixedJsCode } = replaceImportsFromStaticInJsCode({ jsCode });
|
||||||
|
|
||||||
$(element).text(fixedJsCode);
|
$(element).text(fixedJsCode);
|
||||||
});
|
});
|
||||||
|
|
||||||
$("style").each((...[, element]) => {
|
$("style").each((...[, element]) => {
|
||||||
|
const cssCode = $(element).html();
|
||||||
|
|
||||||
|
assert(cssCode !== null);
|
||||||
|
|
||||||
const { fixedCssCode } = replaceImportsInInlineCssCode({
|
const { fixedCssCode } = replaceImportsInInlineCssCode({
|
||||||
"cssCode": $(element).html()!,
|
cssCode,
|
||||||
buildOptions
|
buildOptions
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -100,9 +73,7 @@ export function generateFtlFilesCodeFactory(params: {
|
|||||||
|
|
||||||
$(element).attr(
|
$(element).attr(
|
||||||
attrName,
|
attrName,
|
||||||
buildOptions.isStandalone
|
href.replace(new RegExp(`^${(buildOptions.urlPathname ?? "/").replace(/\//g, "\\/")}`), "${url.resourcesPath}/build/")
|
||||||
? href.replace(new RegExp(`^${(buildOptions.urlPathname ?? "/").replace(/\//g, "\\/")}`), "${url.resourcesPath}/build/")
|
|
||||||
: href.replace(/^\//, `${buildOptions.urlOrigin}/`)
|
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { join as pathJoin, dirname as pathDirname } from "path";
|
import { join as pathJoin, dirname as pathDirname } from "path";
|
||||||
import { assert } from "tsafe/assert";
|
import { assert } from "tsafe/assert";
|
||||||
import { Reflect } from "tsafe/Reflect";
|
|
||||||
import type { BuildOptions } from "./BuildOptions";
|
import type { BuildOptions } from "./BuildOptions";
|
||||||
import type { ThemeType } from "./generateFtl";
|
import type { ThemeType } from "./generateFtl";
|
||||||
|
|
||||||
@ -13,11 +12,7 @@ export type BuildOptionsLike = {
|
|||||||
themeVersion: string;
|
themeVersion: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
assert<BuildOptions extends BuildOptionsLike ? true : false>();
|
||||||
const buildOptions = Reflect<BuildOptions>();
|
|
||||||
|
|
||||||
assert<typeof buildOptions extends BuildOptionsLike ? true : false>();
|
|
||||||
}
|
|
||||||
|
|
||||||
export function generateJavaStackFiles(params: {
|
export function generateJavaStackFiles(params: {
|
||||||
keycloakThemeBuildingDirPath: string;
|
keycloakThemeBuildingDirPath: string;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { join as pathJoin } from "path";
|
import { join as pathJoin } from "path";
|
||||||
import { assert } from "tsafe/assert";
|
import { assert } from "tsafe/assert";
|
||||||
import { Reflect } from "tsafe/Reflect";
|
|
||||||
import type { BuildOptions } from "./BuildOptions";
|
import type { BuildOptions } from "./BuildOptions";
|
||||||
|
|
||||||
export type BuildOptionsLike = {
|
export type BuildOptionsLike = {
|
||||||
@ -9,11 +8,7 @@ export type BuildOptionsLike = {
|
|||||||
extraThemeNames: string[];
|
extraThemeNames: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
assert<BuildOptions extends BuildOptionsLike ? true : false>();
|
||||||
const buildOptions = Reflect<BuildOptions>();
|
|
||||||
|
|
||||||
assert<typeof buildOptions extends BuildOptionsLike ? true : false>();
|
|
||||||
}
|
|
||||||
|
|
||||||
generateStartKeycloakTestingContainer.basename = "start_keycloak_testing_container.sh";
|
generateStartKeycloakTestingContainer.basename = "start_keycloak_testing_container.sh";
|
||||||
|
|
||||||
|
@ -13,39 +13,13 @@ import { readFieldNameUsage } from "./readFieldNameUsage";
|
|||||||
import { readExtraPagesNames } from "./readExtraPageNames";
|
import { readExtraPagesNames } from "./readExtraPageNames";
|
||||||
import { generateMessageProperties } from "./generateMessageProperties";
|
import { generateMessageProperties } from "./generateMessageProperties";
|
||||||
|
|
||||||
export type BuildOptionsLike = BuildOptionsLike.Standalone | BuildOptionsLike.ExternalAssets;
|
export type BuildOptionsLike = {
|
||||||
|
|
||||||
export namespace BuildOptionsLike {
|
|
||||||
export type Common = {
|
|
||||||
themeName: string;
|
themeName: string;
|
||||||
extraThemeProperties: string[] | undefined;
|
extraThemeProperties: string[] | undefined;
|
||||||
themeVersion: string;
|
themeVersion: string;
|
||||||
keycloakVersionDefaultAssets: string;
|
keycloakVersionDefaultAssets: string;
|
||||||
};
|
|
||||||
|
|
||||||
export type Standalone = Common & {
|
|
||||||
isStandalone: true;
|
|
||||||
urlPathname: string | undefined;
|
urlPathname: string | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ExternalAssets = ExternalAssets.SameDomain | ExternalAssets.DifferentDomains;
|
|
||||||
|
|
||||||
export namespace ExternalAssets {
|
|
||||||
export type CommonExternalAssets = Common & {
|
|
||||||
isStandalone: false;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type SameDomain = CommonExternalAssets & {
|
|
||||||
areAppAndKeycloakServerSharingSameDomain: true;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type DifferentDomains = CommonExternalAssets & {
|
|
||||||
areAppAndKeycloakServerSharingSameDomain: false;
|
|
||||||
urlOrigin: string;
|
|
||||||
urlPathname: string | undefined;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert<BuildOptions extends BuildOptionsLike ? true : false>();
|
assert<BuildOptions extends BuildOptionsLike ? true : false>();
|
||||||
|
|
||||||
@ -85,17 +59,16 @@ export async function generateTheme(params: {
|
|||||||
copy_app_resources_to_theme_path: {
|
copy_app_resources_to_theme_path: {
|
||||||
const isFirstPass = themeType.indexOf(themeType) === 0;
|
const isFirstPass = themeType.indexOf(themeType) === 0;
|
||||||
|
|
||||||
if (!isFirstPass && !buildOptions.isStandalone) {
|
if (!isFirstPass) {
|
||||||
break copy_app_resources_to_theme_path;
|
break copy_app_resources_to_theme_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
transformCodebase({
|
transformCodebase({
|
||||||
"destDirPath": buildOptions.isStandalone ? pathJoin(themeDirPath, "resources", "build") : reactAppBuildDirPath,
|
"destDirPath": pathJoin(themeDirPath, "resources", "build"),
|
||||||
"srcDirPath": reactAppBuildDirPath,
|
"srcDirPath": reactAppBuildDirPath,
|
||||||
"transformSourceCode": ({ filePath, sourceCode }) => {
|
"transformSourceCode": ({ filePath, sourceCode }) => {
|
||||||
//NOTE: Prevent cycles, excludes the folder we generated for debug in public/
|
//NOTE: Prevent cycles, excludes the folder we generated for debug in public/
|
||||||
if (
|
if (
|
||||||
buildOptions.isStandalone &&
|
|
||||||
isInside({
|
isInside({
|
||||||
"dirPath": pathJoin(reactAppBuildDirPath, basenameOfKeycloakDirInPublicDir),
|
"dirPath": pathJoin(reactAppBuildDirPath, basenameOfKeycloakDirInPublicDir),
|
||||||
filePath
|
filePath
|
||||||
@ -105,10 +78,6 @@ export async function generateTheme(params: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (/\.css?$/i.test(filePath)) {
|
if (/\.css?$/i.test(filePath)) {
|
||||||
if (!buildOptions.isStandalone) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { cssGlobalsToDefine, fixedCssCode } = replaceImportsInCssCode({
|
const { cssGlobalsToDefine, fixedCssCode } = replaceImportsInCssCode({
|
||||||
"cssCode": sourceCode.toString("utf8")
|
"cssCode": sourceCode.toString("utf8")
|
||||||
});
|
});
|
||||||
@ -128,19 +97,14 @@ export async function generateTheme(params: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (/\.js?$/i.test(filePath)) {
|
if (/\.js?$/i.test(filePath)) {
|
||||||
if (!buildOptions.isStandalone && buildOptions.areAppAndKeycloakServerSharingSameDomain) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { fixedJsCode } = replaceImportsFromStaticInJsCode({
|
const { fixedJsCode } = replaceImportsFromStaticInJsCode({
|
||||||
"jsCode": sourceCode.toString("utf8"),
|
"jsCode": sourceCode.toString("utf8")
|
||||||
buildOptions
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return { "modifiedSourceCode": Buffer.from(fixedJsCode, "utf8") };
|
return { "modifiedSourceCode": Buffer.from(fixedJsCode, "utf8") };
|
||||||
}
|
}
|
||||||
|
|
||||||
return buildOptions.isStandalone ? { "modifiedSourceCode": sourceCode } : undefined;
|
return { "modifiedSourceCode": sourceCode };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,6 @@
|
|||||||
import { ftlValuesGlobalName } from "../ftlValuesGlobalName";
|
import { ftlValuesGlobalName } from "../ftlValuesGlobalName";
|
||||||
import type { BuildOptions } from "../BuildOptions";
|
|
||||||
import { assert } from "tsafe/assert";
|
|
||||||
import { is } from "tsafe/is";
|
|
||||||
import { Reflect } from "tsafe/Reflect";
|
|
||||||
|
|
||||||
export type BuildOptionsLike = BuildOptionsLike.Standalone | BuildOptionsLike.ExternalAssets;
|
export function replaceImportsFromStaticInJsCode(params: { jsCode: string }): { fixedJsCode: string } {
|
||||||
|
|
||||||
export namespace BuildOptionsLike {
|
|
||||||
export type Standalone = {
|
|
||||||
isStandalone: true;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ExternalAssets = {
|
|
||||||
isStandalone: false;
|
|
||||||
urlOrigin: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const buildOptions = Reflect<BuildOptions>();
|
|
||||||
|
|
||||||
assert(!is<BuildOptions.ExternalAssets.CommonExternalAssets>(buildOptions));
|
|
||||||
|
|
||||||
assert<typeof buildOptions extends BuildOptionsLike ? true : false>();
|
|
||||||
}
|
|
||||||
|
|
||||||
export function replaceImportsFromStaticInJsCode(params: { jsCode: string; buildOptions: BuildOptionsLike }): { fixedJsCode: string } {
|
|
||||||
/*
|
/*
|
||||||
NOTE:
|
NOTE:
|
||||||
|
|
||||||
@ -38,7 +13,7 @@ export function replaceImportsFromStaticInJsCode(params: { jsCode: string; build
|
|||||||
will always run in keycloak context.
|
will always run in keycloak context.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { jsCode, buildOptions } = params;
|
const { jsCode } = params;
|
||||||
|
|
||||||
const getReplaceArgs = (language: "js" | "css"): Parameters<typeof String.prototype.replace> => [
|
const getReplaceArgs = (language: "js" | "css"): Parameters<typeof String.prototype.replace> => [
|
||||||
new RegExp(`([a-zA-Z_]+)\\.([a-zA-Z]+)=function\\(([a-zA-Z]+)\\){return"static\\/${language}\\/"`, "g"),
|
new RegExp(`([a-zA-Z_]+)\\.([a-zA-Z]+)=function\\(([a-zA-Z]+)\\){return"static\\/${language}\\/"`, "g"),
|
||||||
@ -46,40 +21,23 @@ export function replaceImportsFromStaticInJsCode(params: { jsCode: string; build
|
|||||||
${n}[(function(){
|
${n}[(function(){
|
||||||
var pd= Object.getOwnPropertyDescriptor(${n}, "p");
|
var pd= Object.getOwnPropertyDescriptor(${n}, "p");
|
||||||
if( pd === undefined || pd.configurable ){
|
if( pd === undefined || pd.configurable ){
|
||||||
${
|
|
||||||
buildOptions.isStandalone
|
|
||||||
? `
|
|
||||||
Object.defineProperty(${n}, "p", {
|
Object.defineProperty(${n}, "p", {
|
||||||
get: function() { return window.${ftlValuesGlobalName}.url.resourcesPath; },
|
get: function() { return window.${ftlValuesGlobalName}.url.resourcesPath; },
|
||||||
set: function (){}
|
set: function (){}
|
||||||
});
|
});
|
||||||
`
|
|
||||||
: `
|
|
||||||
var p= "";
|
|
||||||
Object.defineProperty(${n}, "p", {
|
|
||||||
get: function() { return "${ftlValuesGlobalName}" in window ? "${buildOptions.urlOrigin}/" : p; },
|
|
||||||
set: function (value){ p = value;}
|
|
||||||
});
|
|
||||||
`
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return "${u}";
|
return "${u}";
|
||||||
})()] = function(${e}) { return "${buildOptions.isStandalone ? "/build/" : ""}static/${language}/"`
|
})()] = function(${e}) { return "${true ? "/build/" : ""}static/${language}/"`
|
||||||
];
|
];
|
||||||
|
|
||||||
const fixedJsCode = jsCode
|
const fixedJsCode = jsCode
|
||||||
.replace(...getReplaceArgs("js"))
|
.replace(...getReplaceArgs("js"))
|
||||||
.replace(...getReplaceArgs("css"))
|
.replace(...getReplaceArgs("css"))
|
||||||
.replace(/([a-zA-Z]+\.[a-zA-Z]+)\+"static\//g, (...[, group]) =>
|
.replace(/[a-zA-Z]+\.[a-zA-Z]+\+"static\//g, `window.${ftlValuesGlobalName}.url.resourcesPath + "/build/static/`)
|
||||||
buildOptions.isStandalone
|
|
||||||
? `window.${ftlValuesGlobalName}.url.resourcesPath + "/build/static/`
|
|
||||||
: `("${ftlValuesGlobalName}" in window ? "${buildOptions.urlOrigin}/" : ${group}) + "static/`
|
|
||||||
)
|
|
||||||
//TODO: Write a test case for this
|
//TODO: Write a test case for this
|
||||||
.replace(/".chunk.css",([a-zA-Z])+=([a-zA-Z]+\.[a-zA-Z]+)\+([a-zA-Z]+),/, (...[, group1, group2, group3]) =>
|
.replace(
|
||||||
buildOptions.isStandalone
|
/".chunk.css",([a-zA-Z])+=[a-zA-Z]+\.[a-zA-Z]+\+([a-zA-Z]+),/,
|
||||||
? `".chunk.css",${group1} = window.${ftlValuesGlobalName}.url.resourcesPath + "/build/" + ${group3},`
|
(...[, group1, group2]) => `".chunk.css",${group1} = window.${ftlValuesGlobalName}.url.resourcesPath + "/build/" + ${group2},`
|
||||||
: `".chunk.css",${group1} = ("${ftlValuesGlobalName}" in window ? "${buildOptions.urlOrigin}/" : ${group2}) + ${group3},`
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return { fixedJsCode };
|
return { fixedJsCode };
|
||||||
|
@ -1,20 +1,12 @@
|
|||||||
import * as crypto from "crypto";
|
import * as crypto from "crypto";
|
||||||
import type { BuildOptions } from "../BuildOptions";
|
import type { BuildOptions } from "../BuildOptions";
|
||||||
import { assert } from "tsafe/assert";
|
import { assert } from "tsafe/assert";
|
||||||
import { is } from "tsafe/is";
|
|
||||||
import { Reflect } from "tsafe/Reflect";
|
|
||||||
|
|
||||||
export type BuildOptionsLike = {
|
export type BuildOptionsLike = {
|
||||||
urlPathname: string | undefined;
|
urlPathname: string | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
assert<BuildOptions extends BuildOptionsLike ? true : false>();
|
||||||
const buildOptions = Reflect<BuildOptions>();
|
|
||||||
|
|
||||||
assert(!is<BuildOptions.ExternalAssets.CommonExternalAssets>(buildOptions));
|
|
||||||
|
|
||||||
assert<typeof buildOptions extends BuildOptionsLike ? true : false>();
|
|
||||||
}
|
|
||||||
|
|
||||||
export function replaceImportsInCssCode(params: { cssCode: string }): {
|
export function replaceImportsInCssCode(params: { cssCode: string }): {
|
||||||
fixedCssCode: string;
|
fixedCssCode: string;
|
||||||
|
@ -1,32 +1,11 @@
|
|||||||
import type { BuildOptions } from "../BuildOptions";
|
import type { BuildOptions } from "../BuildOptions";
|
||||||
import { assert } from "tsafe/assert";
|
import { assert } from "tsafe/assert";
|
||||||
import { is } from "tsafe/is";
|
|
||||||
import { Reflect } from "tsafe/Reflect";
|
|
||||||
|
|
||||||
export type BuildOptionsLike = BuildOptionsLike.Standalone | BuildOptionsLike.ExternalAssets;
|
export type BuildOptionsLike = {
|
||||||
|
|
||||||
export namespace BuildOptionsLike {
|
|
||||||
export type Common = {
|
|
||||||
urlPathname: string | undefined;
|
urlPathname: string | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Standalone = Common & {
|
assert<BuildOptions extends BuildOptionsLike ? true : false>();
|
||||||
isStandalone: true;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ExternalAssets = Common & {
|
|
||||||
isStandalone: false;
|
|
||||||
urlOrigin: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const buildOptions = Reflect<BuildOptions>();
|
|
||||||
|
|
||||||
assert(!is<BuildOptions.ExternalAssets.CommonExternalAssets>(buildOptions));
|
|
||||||
|
|
||||||
assert<typeof buildOptions extends BuildOptionsLike ? true : false>();
|
|
||||||
}
|
|
||||||
|
|
||||||
export function replaceImportsInInlineCssCode(params: { cssCode: string; buildOptions: BuildOptionsLike }): {
|
export function replaceImportsInInlineCssCode(params: { cssCode: string; buildOptions: BuildOptionsLike }): {
|
||||||
fixedCssCode: string;
|
fixedCssCode: string;
|
||||||
@ -37,10 +16,7 @@ export function replaceImportsInInlineCssCode(params: { cssCode: string; buildOp
|
|||||||
buildOptions.urlPathname === undefined
|
buildOptions.urlPathname === undefined
|
||||||
? /url\(["']?\/([^/][^)"']+)["']?\)/g
|
? /url\(["']?\/([^/][^)"']+)["']?\)/g
|
||||||
: new RegExp(`url\\(["']?${buildOptions.urlPathname}([^)"']+)["']?\\)`, "g"),
|
: new RegExp(`url\\(["']?${buildOptions.urlPathname}([^)"']+)["']?\\)`, "g"),
|
||||||
(...[, group]) =>
|
(...[, group]) => `url(\${url.resourcesPath}/build/${group})`
|
||||||
`url(${
|
|
||||||
buildOptions.isStandalone ? "${url.resourcesPath}/build/" + group : buildOptions.urlOrigin + (buildOptions.urlPathname ?? "/") + group
|
|
||||||
})`
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return { fixedCssCode };
|
return { fixedCssCode };
|
||||||
|
@ -10,7 +10,7 @@ import { unzip, zip } from "./unzip";
|
|||||||
|
|
||||||
const exec = promisify(execCallback);
|
const exec = promisify(execCallback);
|
||||||
|
|
||||||
function hash(s: string) {
|
function sha256(s: string) {
|
||||||
return createHash("sha256").update(s).digest("hex");
|
return createHash("sha256").update(s).digest("hex");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,8 +112,8 @@ async function getFetchOptions(): Promise<Pick<FetchOptions, "proxy" | "noProxy"
|
|||||||
return { proxy, noProxy, strictSSL, cert, ca: ca.length === 0 ? undefined : ca };
|
return { proxy, noProxy, strictSSL, cert, ca: ca.length === 0 ? undefined : ca };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function downloadAndUnzip(params: {
|
export async function downloadAndUnzip(
|
||||||
projectDirPath: string;
|
params: {
|
||||||
url: string;
|
url: string;
|
||||||
destDirPath: string;
|
destDirPath: string;
|
||||||
specificDirsToExtract?: string[];
|
specificDirsToExtract?: string[];
|
||||||
@ -121,15 +121,26 @@ export async function downloadAndUnzip(params: {
|
|||||||
actionCacheId: string;
|
actionCacheId: string;
|
||||||
action: (params: { destDirPath: string }) => Promise<void>;
|
action: (params: { destDirPath: string }) => Promise<void>;
|
||||||
};
|
};
|
||||||
}) {
|
} & (
|
||||||
const { projectDirPath, url, destDirPath, specificDirsToExtract, preCacheTransform } = params;
|
| {
|
||||||
|
doUseCache: true;
|
||||||
|
projectDirPath: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
doUseCache: false;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
const { url, destDirPath, specificDirsToExtract, preCacheTransform, ...rest } = params;
|
||||||
|
|
||||||
const downloadHash = hash(
|
const hash = sha256(
|
||||||
JSON.stringify({ url }) + (preCacheTransform === undefined ? "" : `${preCacheTransform.actionCacheId}${preCacheTransform.action.toString()}`)
|
JSON.stringify({ url }) + (preCacheTransform === undefined ? "" : `${preCacheTransform.actionCacheId}${preCacheTransform.action.toString()}`)
|
||||||
).substring(0, 15);
|
).substring(0, 15);
|
||||||
const cacheRoot = pathJoin(process.env.XDG_CACHE_HOME ?? pathJoin(projectDirPath, "node_modules", ".cache"), "keycloakify");
|
const cacheRoot = !rest.doUseCache
|
||||||
const zipFilePath = pathJoin(cacheRoot, `_${downloadHash}.zip`);
|
? `tmp_${Math.random().toString().slice(2, 12)}`
|
||||||
const extractDirPath = pathJoin(cacheRoot, `tmp_unzip_${downloadHash}`);
|
: pathJoin(process.env.XDG_CACHE_HOME ?? pathJoin(rest.projectDirPath, "node_modules", ".cache"), "keycloakify");
|
||||||
|
const zipFilePath = pathJoin(cacheRoot, `_${hash}.zip`);
|
||||||
|
const extractDirPath = pathJoin(cacheRoot, `tmp_unzip_${hash}`);
|
||||||
|
|
||||||
if (!(await exists(zipFilePath))) {
|
if (!(await exists(zipFilePath))) {
|
||||||
const opts = await getFetchOptions();
|
const opts = await getFetchOptions();
|
||||||
@ -167,4 +178,8 @@ export async function downloadAndUnzip(params: {
|
|||||||
"srcDirPath": extractDirPath,
|
"srcDirPath": extractDirPath,
|
||||||
"destDirPath": destDirPath
|
"destDirPath": destDirPath
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!rest.doUseCache) {
|
||||||
|
await rm(cacheRoot, { "recursive": true });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,10 +35,7 @@ describe("bin/js-transforms", () => {
|
|||||||
`;
|
`;
|
||||||
it("transforms standalone code properly", () => {
|
it("transforms standalone code properly", () => {
|
||||||
const { fixedJsCode } = replaceImportsFromStaticInJsCode({
|
const { fixedJsCode } = replaceImportsFromStaticInJsCode({
|
||||||
"jsCode": jsCodeUntransformed,
|
"jsCode": jsCodeUntransformed
|
||||||
"buildOptions": {
|
|
||||||
"isStandalone": true
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const fixedJsCodeExpected = `
|
const fixedJsCodeExpected = `
|
||||||
@ -89,66 +86,6 @@ describe("bin/js-transforms", () => {
|
|||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
expect(isSameCode(fixedJsCode, fixedJsCodeExpected)).toBe(true);
|
|
||||||
});
|
|
||||||
it("transforms external app code properly", () => {
|
|
||||||
const { fixedJsCode } = replaceImportsFromStaticInJsCode({
|
|
||||||
"jsCode": jsCodeUntransformed,
|
|
||||||
"buildOptions": {
|
|
||||||
"isStandalone": false,
|
|
||||||
"urlOrigin": "https://demo-app.keycloakify.dev"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const fixedJsCodeExpected = `
|
|
||||||
function f() {
|
|
||||||
return ("kcContext" in window ? "https://demo-app.keycloakify.dev/" : a.p) + "static/js/" + ({}[e] || e) + "." + {
|
|
||||||
3: "0664cdc0"
|
|
||||||
}[e] + ".chunk.js"
|
|
||||||
}
|
|
||||||
|
|
||||||
function sameAsF() {
|
|
||||||
return ("kcContext" in window ? "https://demo-app.keycloakify.dev/" : a.p) + "static/js/" + ({}[e] || e) + "." + {
|
|
||||||
3: "0664cdc0"
|
|
||||||
}[e] + ".chunk.js"
|
|
||||||
}
|
|
||||||
|
|
||||||
__webpack_require__[(function (){
|
|
||||||
var pd= Object.getOwnPropertyDescriptor(__webpack_require__, "p");
|
|
||||||
if( pd === undefined || pd.configurable ){
|
|
||||||
var p= "";
|
|
||||||
Object.defineProperty(__webpack_require__, "p", {
|
|
||||||
get: function() { return "kcContext" in window ? "https://demo-app.keycloakify.dev/" : p; },
|
|
||||||
set: function (value){ p = value; }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return "u";
|
|
||||||
})()] = function(e) {
|
|
||||||
return "static/js/" + e + "." + {
|
|
||||||
147: "6c5cee76",
|
|
||||||
787: "8da10fcf",
|
|
||||||
922: "be170a73"
|
|
||||||
} [e] + ".chunk.js"
|
|
||||||
}
|
|
||||||
|
|
||||||
t[(function (){
|
|
||||||
var pd= Object.getOwnPropertyDescriptor(t, "p");
|
|
||||||
if( pd === undefined || pd.configurable ){
|
|
||||||
var p= "";
|
|
||||||
Object.defineProperty(t, "p", {
|
|
||||||
get: function() { return "kcContext" in window ? "https://demo-app.keycloakify.dev/" : p; },
|
|
||||||
set: function (value){ p = value; }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return "miniCssF";
|
|
||||||
})()] = function(e) {
|
|
||||||
return "static/css/" + e + "." + {
|
|
||||||
164:"dcfd7749",
|
|
||||||
908:"67c9ed2c"
|
|
||||||
} [e] + ".chunk.css"
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
expect(isSameCode(fixedJsCode, fixedJsCodeExpected)).toBe(true);
|
expect(isSameCode(fixedJsCode, fixedJsCodeExpected)).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -304,7 +241,6 @@ describe("bin/css-inline-transforms", () => {
|
|||||||
const { fixedCssCode } = replaceImportsInInlineCssCode({
|
const { fixedCssCode } = replaceImportsInInlineCssCode({
|
||||||
cssCode,
|
cssCode,
|
||||||
"buildOptions": {
|
"buildOptions": {
|
||||||
"isStandalone": true,
|
|
||||||
"urlPathname": undefined
|
"urlPathname": undefined
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -344,53 +280,6 @@ describe("bin/css-inline-transforms", () => {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
expect(isSameCode(fixedCssCode, fixedCssCodeExpected)).toBe(true);
|
|
||||||
});
|
|
||||||
it("transforms css for external app properly", () => {
|
|
||||||
const { fixedCssCode } = replaceImportsInInlineCssCode({
|
|
||||||
cssCode,
|
|
||||||
"buildOptions": {
|
|
||||||
"isStandalone": false,
|
|
||||||
"urlOrigin": "https://demo-app.keycloakify.dev",
|
|
||||||
"urlPathname": undefined
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const fixedCssCodeExpected = `
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
font-display: swap;
|
|
||||||
src: url(https://demo-app.keycloakify.dev/fonts/WorkSans/worksans-regular-webfont.woff2)
|
|
||||||
format("woff2");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 500;
|
|
||||||
font-display: swap;
|
|
||||||
src: url(https://demo-app.keycloakify.dev/fonts/WorkSans/worksans-medium-webfont.woff2)
|
|
||||||
format("woff2");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 600;
|
|
||||||
font-display: swap;
|
|
||||||
src: url(https://demo-app.keycloakify.dev/fonts/WorkSans/worksans-semibold-webfont.woff2)
|
|
||||||
format("woff2");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 700;
|
|
||||||
font-display: swap;
|
|
||||||
src: url(https://demo-app.keycloakify.dev/fonts/WorkSans/worksans-bold-webfont.woff2)
|
|
||||||
format("woff2");
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
expect(isSameCode(fixedCssCode, fixedCssCodeExpected)).toBe(true);
|
expect(isSameCode(fixedCssCode, fixedCssCodeExpected)).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -430,7 +319,6 @@ describe("bin/css-inline-transforms", () => {
|
|||||||
const { fixedCssCode } = replaceImportsInInlineCssCode({
|
const { fixedCssCode } = replaceImportsInInlineCssCode({
|
||||||
cssCode,
|
cssCode,
|
||||||
"buildOptions": {
|
"buildOptions": {
|
||||||
"isStandalone": true,
|
|
||||||
"urlPathname": "/x/y/z/"
|
"urlPathname": "/x/y/z/"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -470,53 +358,6 @@ describe("bin/css-inline-transforms", () => {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
expect(isSameCode(fixedCssCode, fixedCssCodeExpected)).toBe(true);
|
|
||||||
});
|
|
||||||
it("transforms css for external app properly", () => {
|
|
||||||
const { fixedCssCode } = replaceImportsInInlineCssCode({
|
|
||||||
cssCode,
|
|
||||||
"buildOptions": {
|
|
||||||
"isStandalone": false,
|
|
||||||
"urlOrigin": "https://demo-app.keycloakify.dev",
|
|
||||||
"urlPathname": "/x/y/z/"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const fixedCssCodeExpected = `
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
font-display: swap;
|
|
||||||
src: url(https://demo-app.keycloakify.dev/x/y/z/fonts/WorkSans/worksans-regular-webfont.woff2)
|
|
||||||
format("woff2");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 500;
|
|
||||||
font-display: swap;
|
|
||||||
src: url(https://demo-app.keycloakify.dev/x/y/z/fonts/WorkSans/worksans-medium-webfont.woff2)
|
|
||||||
format("woff2");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 600;
|
|
||||||
font-display: swap;
|
|
||||||
src: url(https://demo-app.keycloakify.dev/x/y/z/fonts/WorkSans/worksans-semibold-webfont.woff2)
|
|
||||||
format("woff2");
|
|
||||||
}
|
|
||||||
@font-face {
|
|
||||||
font-family: "Work Sans";
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 700;
|
|
||||||
font-display: swap;
|
|
||||||
src: url(https://demo-app.keycloakify.dev/x/y/z/fonts/WorkSans/worksans-bold-webfont.woff2)
|
|
||||||
format("woff2");
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
expect(isSameCode(fixedCssCode, fixedCssCodeExpected)).toBe(true);
|
expect(isSameCode(fixedCssCode, fixedCssCodeExpected)).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -12,7 +12,8 @@ export const sampleReactProjectDirPath = pathJoin(getProjectRoot(), "sample_reac
|
|||||||
async function setupSampleReactProject(destDir: string) {
|
async function setupSampleReactProject(destDir: string) {
|
||||||
await downloadAndUnzip({
|
await downloadAndUnzip({
|
||||||
"url": "https://github.com/keycloakify/keycloakify/releases/download/v0.0.1/sample_build_dir_and_package_json.zip",
|
"url": "https://github.com/keycloakify/keycloakify/releases/download/v0.0.1/sample_build_dir_and_package_json.zip",
|
||||||
"destDirPath": destDir
|
"destDirPath": destDir,
|
||||||
|
"doUseCache": false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let parsedPackageJson: Record<string, unknown> = {};
|
let parsedPackageJson: Record<string, unknown> = {};
|
||||||
@ -51,17 +52,19 @@ describe("Sample Project", () => {
|
|||||||
await setupSampleReactProject(sampleReactProjectDirPath);
|
await setupSampleReactProject(sampleReactProjectDirPath);
|
||||||
await initializeEmailTheme();
|
await initializeEmailTheme();
|
||||||
|
|
||||||
|
const projectDirPath = process.cwd();
|
||||||
|
|
||||||
const destDirPath = pathJoin(
|
const destDirPath = pathJoin(
|
||||||
readBuildOptions({
|
readBuildOptions({
|
||||||
"processArgv": ["--silent"],
|
"processArgv": ["--silent"],
|
||||||
"projectDirPath": process.cwd()
|
projectDirPath
|
||||||
}).keycloakifyBuildDirPath,
|
}).keycloakifyBuildDirPath,
|
||||||
"src",
|
"src",
|
||||||
"main",
|
"main",
|
||||||
"resources",
|
"resources",
|
||||||
"theme"
|
"theme"
|
||||||
);
|
);
|
||||||
await downloadBuiltinKeycloakTheme({ destDirPath, keycloakVersion: "11.0.3", "isSilent": false });
|
await downloadBuiltinKeycloakTheme({ destDirPath, "keycloakVersion": "11.0.3", projectDirPath });
|
||||||
},
|
},
|
||||||
{ timeout: 90000 }
|
{ timeout: 90000 }
|
||||||
);
|
);
|
||||||
@ -77,17 +80,19 @@ describe("Sample Project", () => {
|
|||||||
await setupSampleReactProject(pathJoin(sampleReactProjectDirPath, "custom_input"));
|
await setupSampleReactProject(pathJoin(sampleReactProjectDirPath, "custom_input"));
|
||||||
await initializeEmailTheme();
|
await initializeEmailTheme();
|
||||||
|
|
||||||
|
const projectDirPath = process.cwd();
|
||||||
|
|
||||||
const destDirPath = pathJoin(
|
const destDirPath = pathJoin(
|
||||||
readBuildOptions({
|
readBuildOptions({
|
||||||
"processArgv": ["--silent"],
|
"processArgv": ["--silent"],
|
||||||
"projectDirPath": process.cwd()
|
projectDirPath
|
||||||
}).keycloakifyBuildDirPath,
|
}).keycloakifyBuildDirPath,
|
||||||
"src",
|
"src",
|
||||||
"main",
|
"main",
|
||||||
"resources",
|
"resources",
|
||||||
"theme"
|
"theme"
|
||||||
);
|
);
|
||||||
await downloadBuiltinKeycloakTheme({ destDirPath, "keycloakVersion": "11.0.3", "isSilent": false });
|
await downloadBuiltinKeycloakTheme({ destDirPath, "keycloakVersion": "11.0.3", projectDirPath });
|
||||||
},
|
},
|
||||||
{ timeout: 90000 }
|
{ timeout: 90000 }
|
||||||
);
|
);
|
||||||
|
@ -3,6 +3,7 @@ import { downloadAndUnzip } from "keycloakify/bin/tools/downloadAndUnzip";
|
|||||||
export async function setupSampleReactProject(destDirPath: string) {
|
export async function setupSampleReactProject(destDirPath: string) {
|
||||||
await downloadAndUnzip({
|
await downloadAndUnzip({
|
||||||
"url": "https://github.com/keycloakify/keycloakify/releases/download/v0.0.1/sample_build_dir_and_package_json.zip",
|
"url": "https://github.com/keycloakify/keycloakify/releases/download/v0.0.1/sample_build_dir_and_package_json.zip",
|
||||||
"destDirPath": destDirPath
|
"destDirPath": destDirPath,
|
||||||
|
"doUseCache": false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user