Compare commits
30 Commits
v6.0.0-bet
...
v6.1.0
Author | SHA1 | Date | |
---|---|---|---|
d8b00da3a1 | |||
a24945bc1b | |||
158759493f | |||
36e32d6ddc | |||
84908e2ec0 | |||
a2dc51d811 | |||
fb3b0e2c29 | |||
1a3e4c68bb | |||
11b2342da0 | |||
80d4a808d3 | |||
da4146eb59 | |||
a0be35db8b | |||
14db9cd523 | |||
0c315385dd | |||
c0a0eb02fb | |||
ee407c32ad | |||
9262d21829 | |||
a13f710325 | |||
eac1a6036f | |||
987f3d7586 | |||
875322669c | |||
33a264b3d0 | |||
c059eff170 | |||
b4a22fc9dd | |||
6d1cbdc463 | |||
2bfbba4daf | |||
21ffe82bde | |||
8e6f597027 | |||
16c5065560 | |||
c4b985f1a4 |
4
.github/FUNDING.yaml
vendored
Normal file
4
.github/FUNDING.yaml
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [garronej]
|
||||
custom: ['https://www.ringerhq.com/experts/garronej']
|
2
.github/workflows/ci.yaml
vendored
2
.github/workflows/ci.yaml
vendored
@ -3,11 +3,9 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- v6
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- v6
|
||||
|
||||
jobs:
|
||||
|
||||
|
17
README.md
17
README.md
@ -2,7 +2,7 @@
|
||||
<img src="https://user-images.githubusercontent.com/6702424/109387840-eba11f80-7903-11eb-9050-db1dad883f78.png">
|
||||
</p>
|
||||
<p align="center">
|
||||
<i>🔏 Create Keycloak themes using React 🔏</i>
|
||||
<i>🔏 Create Keycloak themes using React 🔏</i>
|
||||
<br>
|
||||
<br>
|
||||
<a href="https://github.com/garronej/keycloakify/actions">
|
||||
@ -27,7 +27,14 @@
|
||||
<a href="https://www.keycloakify.dev">Home</a>
|
||||
-
|
||||
<a href="https://docs.keycloakify.dev">Documentation</a>
|
||||
</p>
|
||||
</p>
|
||||
<p align="center"> ---- Project starter / Demo setup ---- </p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/garronej/keycloakify-starter">CSS Level customization</a>
|
||||
-
|
||||
<a href="https://github.com/garronej/keycloakify-advanced-starter">Component Level customization</a>
|
||||
</p>
|
||||
<p align="center"> ---- </p>
|
||||
|
||||
</p>
|
||||
|
||||
@ -36,6 +43,10 @@
|
||||
<img src="https://user-images.githubusercontent.com/6702424/110260457-a1c3d380-7fac-11eb-853a-80459b65626b.png">
|
||||
</p>
|
||||
|
||||
> 🗣 V6 have been released 🎉
|
||||
> [It features major improvements](https://github.com/InseeFrLab/keycloakify#600).
|
||||
> Checkout [the migration guide](https://docs.keycloakify.dev/v5-to-v6).
|
||||
|
||||
# Changelog highlights
|
||||
|
||||
## 6.0.0
|
||||
@ -45,7 +56,7 @@
|
||||
- Real i18n API.
|
||||
- Actual documentation for build options.
|
||||
|
||||
Checkout the migration guide.
|
||||
Checkout [the migration guide](https://docs.keycloakify.dev/v5-to-v6)
|
||||
|
||||
## 5.8.0
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "keycloakify",
|
||||
"version": "6.0.0-beta.12",
|
||||
"version": "6.1.0",
|
||||
"description": "Keycloak theme generator for Reacts app",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -60,6 +60,7 @@
|
||||
"devDependencies": {
|
||||
"@emotion/react": "^11.4.1",
|
||||
"@types/memoizee": "^0.4.7",
|
||||
"@types/minimist": "^1.2.2",
|
||||
"@types/node": "^17.0.25",
|
||||
"@types/react": "18.0.9",
|
||||
"copyfiles": "^2.4.1",
|
||||
@ -78,12 +79,13 @@
|
||||
"evt": "^2.4.0",
|
||||
"memoizee": "^0.4.15",
|
||||
"minimal-polyfills": "^2.2.2",
|
||||
"minimist": "^1.2.6",
|
||||
"path-browserify": "^1.0.1",
|
||||
"powerhooks": "^0.20.15",
|
||||
"react-markdown": "^5.0.3",
|
||||
"scripting-tools": "^0.19.13",
|
||||
"tsafe": "^1.0.1",
|
||||
"tss-react": "^4.0.0",
|
||||
"tss-react": "^4.1.3",
|
||||
"zod": "^3.17.10"
|
||||
}
|
||||
}
|
||||
|
@ -6,11 +6,15 @@ import { join as pathJoin, basename as pathBasename } from "path";
|
||||
import { transformCodebase } from "./tools/transformCodebase";
|
||||
import { promptKeycloakVersion } from "./promptKeycloakVersion";
|
||||
import * as fs from "fs";
|
||||
import { getCliOptions } from "./tools/cliOptions";
|
||||
import { getLogger } from "./tools/logger";
|
||||
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
const { isSilent } = getCliOptions(process.argv.slice(2));
|
||||
const logger = getLogger({ isSilent });
|
||||
if (fs.existsSync(keycloakThemeEmailDirPath)) {
|
||||
console.log(`There is already a ./${pathBasename(keycloakThemeEmailDirPath)} directory in your project. Aborting.`);
|
||||
logger.warn(`There is already a ./${pathBasename(keycloakThemeEmailDirPath)} directory in your project. Aborting.`);
|
||||
|
||||
process.exit(-1);
|
||||
}
|
||||
@ -21,7 +25,8 @@ if (require.main === module) {
|
||||
|
||||
downloadBuiltinKeycloakTheme({
|
||||
keycloakVersion,
|
||||
"destDirPath": builtinKeycloakThemeTmpDirPath
|
||||
"destDirPath": builtinKeycloakThemeTmpDirPath,
|
||||
isSilent
|
||||
});
|
||||
|
||||
transformCodebase({
|
||||
@ -29,7 +34,7 @@ if (require.main === module) {
|
||||
"destDirPath": keycloakThemeEmailDirPath
|
||||
});
|
||||
|
||||
console.log(`./${pathBasename(keycloakThemeEmailDirPath)} ready to be customized`);
|
||||
logger.log(`./${pathBasename(keycloakThemeEmailDirPath)} ready to be customized`);
|
||||
|
||||
fs.rmSync(builtinKeycloakThemeTmpDirPath, { "recursive": true, "force": true });
|
||||
})();
|
||||
|
@ -4,31 +4,37 @@ import { keycloakThemeBuildingDirPath } from "./keycloakify";
|
||||
import { join as pathJoin } from "path";
|
||||
import { downloadAndUnzip } from "./tools/downloadAndUnzip";
|
||||
import { promptKeycloakVersion } from "./promptKeycloakVersion";
|
||||
import { getCliOptions } from "./tools/cliOptions";
|
||||
import { getLogger } from "./tools/logger";
|
||||
|
||||
export function downloadBuiltinKeycloakTheme(params: { keycloakVersion: string; destDirPath: string }) {
|
||||
const { keycloakVersion, destDirPath } = params;
|
||||
export function downloadBuiltinKeycloakTheme(params: { keycloakVersion: string; destDirPath: string; isSilent: boolean }) {
|
||||
const { keycloakVersion, destDirPath, isSilent } = params;
|
||||
|
||||
for (const ext of ["", "-community"]) {
|
||||
downloadAndUnzip({
|
||||
"destDirPath": destDirPath,
|
||||
"url": `https://github.com/keycloak/keycloak/archive/refs/tags/${keycloakVersion}.zip`,
|
||||
"pathOfDirToExtractInArchive": `keycloak-${keycloakVersion}/themes/src/main/resources${ext}/theme`,
|
||||
"cacheDirPath": pathJoin(keycloakThemeBuildingDirPath, ".cache")
|
||||
"cacheDirPath": pathJoin(keycloakThemeBuildingDirPath, ".cache"),
|
||||
isSilent
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
const { isSilent } = getCliOptions(process.argv.slice(2));
|
||||
const logger = getLogger({ isSilent });
|
||||
const { keycloakVersion } = await promptKeycloakVersion();
|
||||
|
||||
const destDirPath = pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources", "theme");
|
||||
|
||||
console.log(`Downloading builtins theme of Keycloak ${keycloakVersion} here ${destDirPath}`);
|
||||
logger.log(`Downloading builtins theme of Keycloak ${keycloakVersion} here ${destDirPath}`);
|
||||
|
||||
downloadBuiltinKeycloakTheme({
|
||||
keycloakVersion,
|
||||
destDirPath
|
||||
destDirPath,
|
||||
isSilent
|
||||
});
|
||||
})();
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import { crawl } from "./tools/crawl";
|
||||
import { downloadBuiltinKeycloakTheme } from "./download-builtin-keycloak-theme";
|
||||
import { getProjectRoot } from "./tools/getProjectRoot";
|
||||
import { rm_rf, rm_r } from "./tools/rm";
|
||||
import { getCliOptions } from "./tools/cliOptions";
|
||||
import { getLogger } from "./tools/logger";
|
||||
|
||||
//NOTE: To run without argument when we want to generate src/i18n/generated_kcMessages files,
|
||||
// update the version array for generating for newer version.
|
||||
@ -12,8 +14,11 @@ import { rm_rf, rm_r } from "./tools/rm";
|
||||
//@ts-ignore
|
||||
const propertiesParser = require("properties-parser");
|
||||
|
||||
const { isSilent } = getCliOptions(process.argv.slice(2));
|
||||
const logger = getLogger({ isSilent });
|
||||
|
||||
for (const keycloakVersion of ["11.0.3", "15.0.2", "18.0.1"]) {
|
||||
console.log({ keycloakVersion });
|
||||
logger.log(JSON.stringify({ keycloakVersion }));
|
||||
|
||||
const tmpDirPath = pathJoin(getProjectRoot(), "tmp_xImOef9dOd44");
|
||||
|
||||
@ -21,7 +26,8 @@ for (const keycloakVersion of ["11.0.3", "15.0.2", "18.0.1"]) {
|
||||
|
||||
downloadBuiltinKeycloakTheme({
|
||||
keycloakVersion,
|
||||
"destDirPath": tmpDirPath
|
||||
"destDirPath": tmpDirPath,
|
||||
isSilent
|
||||
});
|
||||
|
||||
type Dictionary = { [idiomId: string]: string };
|
||||
@ -75,7 +81,7 @@ for (const keycloakVersion of ["11.0.3", "15.0.2", "18.0.1"]) {
|
||||
)
|
||||
);
|
||||
|
||||
console.log(`${filePath} wrote`);
|
||||
logger.log(`${filePath} wrote`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ type ParsedPackageJson = {
|
||||
keycloakify?: {
|
||||
extraPages?: string[];
|
||||
extraThemeProperties?: string[];
|
||||
isAppAndKeycloakServerSharingSameDomain?: boolean;
|
||||
areAppAndKeycloakServerSharingSameDomain?: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
@ -23,7 +23,7 @@ const zParsedPackageJson = z.object({
|
||||
.object({
|
||||
"extraPages": z.array(z.string()).optional(),
|
||||
"extraThemeProperties": z.array(z.string()).optional(),
|
||||
"isAppAndKeycloakServerSharingSameDomain": z.boolean().optional()
|
||||
"areAppAndKeycloakServerSharingSameDomain": z.boolean().optional()
|
||||
})
|
||||
.optional()
|
||||
});
|
||||
@ -35,6 +35,7 @@ export type BuildOptions = BuildOptions.Standalone | BuildOptions.ExternalAssets
|
||||
|
||||
export namespace BuildOptions {
|
||||
export type Common = {
|
||||
isSilent: boolean;
|
||||
version: string;
|
||||
themeName: string;
|
||||
extraPages?: string[];
|
||||
@ -56,11 +57,11 @@ export namespace BuildOptions {
|
||||
};
|
||||
|
||||
export type SameDomain = CommonExternalAssets & {
|
||||
isAppAndKeycloakServerSharingSameDomain: true;
|
||||
areAppAndKeycloakServerSharingSameDomain: true;
|
||||
};
|
||||
|
||||
export type DifferentDomains = CommonExternalAssets & {
|
||||
isAppAndKeycloakServerSharingSameDomain: false;
|
||||
areAppAndKeycloakServerSharingSameDomain: false;
|
||||
urlOrigin: string;
|
||||
urlPathname: string | undefined;
|
||||
};
|
||||
@ -71,8 +72,9 @@ export function readBuildOptions(params: {
|
||||
packageJson: string;
|
||||
CNAME: string | undefined;
|
||||
isExternalAssetsCliParamProvided: boolean;
|
||||
isSilent: boolean;
|
||||
}): BuildOptions {
|
||||
const { packageJson, CNAME, isExternalAssetsCliParamProvided } = params;
|
||||
const { packageJson, CNAME, isExternalAssetsCliParamProvided, isSilent } = params;
|
||||
|
||||
const parsedPackageJson = zParsedPackageJson.parse(JSON.parse(packageJson));
|
||||
|
||||
@ -130,7 +132,8 @@ export function readBuildOptions(params: {
|
||||
})(),
|
||||
"version": version,
|
||||
extraPages,
|
||||
extraThemeProperties
|
||||
extraThemeProperties,
|
||||
isSilent
|
||||
};
|
||||
})();
|
||||
|
||||
@ -140,10 +143,10 @@ export function readBuildOptions(params: {
|
||||
"isStandalone": false
|
||||
});
|
||||
|
||||
if (parsedPackageJson.keycloakify?.isAppAndKeycloakServerSharingSameDomain) {
|
||||
if (parsedPackageJson.keycloakify?.areAppAndKeycloakServerSharingSameDomain) {
|
||||
return id<BuildOptions.ExternalAssets.SameDomain>({
|
||||
...commonExternalAssets,
|
||||
"isAppAndKeycloakServerSharingSameDomain": true
|
||||
"areAppAndKeycloakServerSharingSameDomain": true
|
||||
});
|
||||
} else {
|
||||
assert(
|
||||
@ -155,14 +158,14 @@ export function readBuildOptions(params: {
|
||||
"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": { "isAppAndKeycloakServerSharingSameDomain": true }',
|
||||
'admin UI, you can set "keycloakify": { "areAppAndKeycloakServerSharingSameDomain": true }',
|
||||
"in your package.json"
|
||||
].join(" ")
|
||||
);
|
||||
|
||||
return id<BuildOptions.ExternalAssets.DifferentDomains>({
|
||||
...commonExternalAssets,
|
||||
"isAppAndKeycloakServerSharingSameDomain": false,
|
||||
"areAppAndKeycloakServerSharingSameDomain": false,
|
||||
"urlOrigin": url.origin,
|
||||
"urlPathname": url.pathname
|
||||
});
|
||||
|
@ -46,11 +46,11 @@ export namespace BuildOptionsLike {
|
||||
};
|
||||
|
||||
export type SameDomain = CommonExternalAssets & {
|
||||
isAppAndKeycloakServerSharingSameDomain: true;
|
||||
areAppAndKeycloakServerSharingSameDomain: true;
|
||||
};
|
||||
|
||||
export type DifferentDomains = CommonExternalAssets & {
|
||||
isAppAndKeycloakServerSharingSameDomain: false;
|
||||
areAppAndKeycloakServerSharingSameDomain: false;
|
||||
urlOrigin: string;
|
||||
urlPathname: string | undefined;
|
||||
};
|
||||
@ -76,7 +76,7 @@ export function generateFtlFilesCodeFactory(params: {
|
||||
const $ = cheerio.load(indexHtmlCode);
|
||||
|
||||
fix_imports_statements: {
|
||||
if (!buildOptions.isStandalone && buildOptions.isAppAndKeycloakServerSharingSameDomain) {
|
||||
if (!buildOptions.isStandalone && buildOptions.areAppAndKeycloakServerSharingSameDomain) {
|
||||
break fix_imports_statements;
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ import { isInside } from "../tools/isInside";
|
||||
import type { BuildOptions } from "./BuildOptions";
|
||||
import { assert } from "tsafe/assert";
|
||||
import { Reflect } from "tsafe/Reflect";
|
||||
import { getLogger } from "../tools/logger";
|
||||
|
||||
export type BuildOptionsLike = BuildOptionsLike.Standalone | BuildOptionsLike.ExternalAssets;
|
||||
|
||||
@ -19,6 +20,7 @@ export namespace BuildOptionsLike {
|
||||
themeName: string;
|
||||
extraPages?: string[];
|
||||
extraThemeProperties?: string[];
|
||||
isSilent: boolean;
|
||||
};
|
||||
|
||||
export type Standalone = Common & {
|
||||
@ -34,11 +36,11 @@ export namespace BuildOptionsLike {
|
||||
};
|
||||
|
||||
export type SameDomain = CommonExternalAssets & {
|
||||
isAppAndKeycloakServerSharingSameDomain: true;
|
||||
areAppAndKeycloakServerSharingSameDomain: true;
|
||||
};
|
||||
|
||||
export type DifferentDomains = CommonExternalAssets & {
|
||||
isAppAndKeycloakServerSharingSameDomain: false;
|
||||
areAppAndKeycloakServerSharingSameDomain: false;
|
||||
urlOrigin: string;
|
||||
urlPathname: string | undefined;
|
||||
};
|
||||
@ -60,6 +62,7 @@ export function generateKeycloakThemeResources(params: {
|
||||
}): { doBundlesEmailTemplate: boolean } {
|
||||
const { reactAppBuildDirPath, keycloakThemeBuildingDirPath, keycloakThemeEmailDirPath, keycloakVersion, buildOptions } = params;
|
||||
|
||||
const logger = getLogger({ isSilent: buildOptions.isSilent });
|
||||
const themeDirPath = pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources", "theme", buildOptions.themeName, "login");
|
||||
|
||||
let allCssGlobalsToDefine: Record<string, string> = {};
|
||||
@ -97,7 +100,7 @@ export function generateKeycloakThemeResources(params: {
|
||||
}
|
||||
|
||||
if (/\.js?$/i.test(filePath)) {
|
||||
if (!buildOptions.isStandalone && buildOptions.isAppAndKeycloakServerSharingSameDomain) {
|
||||
if (!buildOptions.isStandalone && buildOptions.areAppAndKeycloakServerSharingSameDomain) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@ -117,7 +120,7 @@ export function generateKeycloakThemeResources(params: {
|
||||
|
||||
email: {
|
||||
if (!fs.existsSync(keycloakThemeEmailDirPath)) {
|
||||
console.log(
|
||||
logger.log(
|
||||
[
|
||||
`Not bundling email template because ${pathBasename(keycloakThemeEmailDirPath)} does not exist`,
|
||||
`To start customizing the email template, run: 👉 npx create-keycloak-email-directory 👈`
|
||||
@ -154,7 +157,8 @@ export function generateKeycloakThemeResources(params: {
|
||||
|
||||
downloadBuiltinKeycloakTheme({
|
||||
keycloakVersion,
|
||||
"destDirPath": tmpDirPath
|
||||
"destDirPath": tmpDirPath,
|
||||
isSilent: buildOptions.isSilent
|
||||
});
|
||||
|
||||
const themeResourcesDirPath = pathJoin(themeDirPath, "resources");
|
||||
|
@ -5,6 +5,8 @@ import * as child_process from "child_process";
|
||||
import { generateStartKeycloakTestingContainer } from "./generateStartKeycloakTestingContainer";
|
||||
import * as fs from "fs";
|
||||
import { readBuildOptions } from "./BuildOptions";
|
||||
import { getLogger } from "../tools/logger";
|
||||
import { getCliOptions } from "../tools/cliOptions";
|
||||
|
||||
const reactProjectDirPath = process.cwd();
|
||||
|
||||
@ -12,7 +14,9 @@ export const keycloakThemeBuildingDirPath = pathJoin(reactProjectDirPath, "build
|
||||
export const keycloakThemeEmailDirPath = pathJoin(keycloakThemeBuildingDirPath, "..", "keycloak_email");
|
||||
|
||||
export function main() {
|
||||
console.log("🔏 Building the keycloak theme...⌚");
|
||||
const { isSilent, hasExternalAssets } = getCliOptions(process.argv.slice(2));
|
||||
const logger = getLogger({ isSilent });
|
||||
logger.log("🔏 Building the keycloak theme...⌚");
|
||||
|
||||
const buildOptions = readBuildOptions({
|
||||
"packageJson": fs.readFileSync(pathJoin(reactProjectDirPath, "package.json")).toString("utf8"),
|
||||
@ -25,7 +29,8 @@ export function main() {
|
||||
|
||||
return fs.readFileSync(cnameFilePath).toString("utf8");
|
||||
})(),
|
||||
"isExternalAssetsCliParamProvided": process.argv[2]?.toLowerCase() === "--external-assets"
|
||||
"isExternalAssetsCliParamProvided": hasExternalAssets,
|
||||
"isSilent": isSilent
|
||||
});
|
||||
|
||||
const { doBundlesEmailTemplate } = generateKeycloakThemeResources({
|
||||
@ -59,7 +64,7 @@ export function main() {
|
||||
buildOptions
|
||||
});
|
||||
|
||||
console.log(
|
||||
logger.log(
|
||||
[
|
||||
"",
|
||||
`✅ Your keycloak theme has been generated and bundled into ./${pathRelative(reactProjectDirPath, jarFilePath)} 🚀`,
|
||||
|
@ -41,10 +41,10 @@ export function replaceImportsFromStaticInJsCode(params: { jsCode: string; build
|
||||
const { jsCode, buildOptions } = params;
|
||||
|
||||
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"),
|
||||
(...[, n, u, e]) => `
|
||||
${n}[(function(){
|
||||
var pd= Object.getOwnPropertyDescriptor(n, "p");
|
||||
var pd= Object.getOwnPropertyDescriptor(${n}, "p");
|
||||
if( pd === undefined || pd.configurable ){
|
||||
${
|
||||
buildOptions.isStandalone
|
||||
@ -57,7 +57,7 @@ export function replaceImportsFromStaticInJsCode(params: { jsCode: string; build
|
||||
: `
|
||||
var p= "";
|
||||
Object.defineProperty(${n}, "p", {
|
||||
get: function() { return ("${ftlValuesGlobalName}" in window ? "${buildOptions.urlOrigin}" : "") + p; },
|
||||
get: function() { return "${ftlValuesGlobalName}" in window ? "${buildOptions.urlOrigin}/" : p; },
|
||||
set: function (value){ p = value;}
|
||||
});
|
||||
`
|
||||
@ -73,13 +73,13 @@ export function replaceImportsFromStaticInJsCode(params: { jsCode: string; build
|
||||
.replace(/([a-zA-Z]+\.[a-zA-Z]+)\+"static\//g, (...[, group]) =>
|
||||
buildOptions.isStandalone
|
||||
? `window.${ftlValuesGlobalName}.url.resourcesPath + "/build/static/`
|
||||
: `("${ftlValuesGlobalName}" in window ? "${buildOptions.urlOrigin}" : "") + ${group} + "static/`
|
||||
: `("${ftlValuesGlobalName}" in window ? "${buildOptions.urlOrigin}/" : ${group}) + "static/`
|
||||
)
|
||||
//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]) =>
|
||||
buildOptions.isStandalone
|
||||
? `".chunk.css",${group1} = window.${ftlValuesGlobalName}.url.resourcesPath + "/build/" + ${group3},`
|
||||
: `".chunk.css",${group1} = ("${ftlValuesGlobalName}" in window ? "${buildOptions.urlOrigin}" : "") + ${group2} + ${group3},`
|
||||
: `".chunk.css",${group1} = ("${ftlValuesGlobalName}" in window ? "${buildOptions.urlOrigin}/" : ${group2}) + ${group3},`
|
||||
);
|
||||
|
||||
return { fixedJsCode };
|
||||
|
15
src/bin/tools/cliOptions.ts
Normal file
15
src/bin/tools/cliOptions.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import parseArgv from "minimist";
|
||||
|
||||
export type CliOptions = {
|
||||
isSilent: boolean;
|
||||
hasExternalAssets: boolean;
|
||||
};
|
||||
|
||||
export const getCliOptions = (processArgv: string[]): CliOptions => {
|
||||
const argv = parseArgv(processArgv);
|
||||
|
||||
return {
|
||||
isSilent: typeof argv["silent"] === "boolean" ? argv["silent"] : false,
|
||||
hasExternalAssets: typeof argv["external-assets"] === "boolean" ? argv["external-assets"] : false
|
||||
};
|
||||
};
|
@ -6,7 +6,13 @@ import { rm, rm_rf } from "./rm";
|
||||
import * as crypto from "crypto";
|
||||
|
||||
/** assert url ends with .zip */
|
||||
export function downloadAndUnzip(params: { url: string; destDirPath: string; pathOfDirToExtractInArchive?: string; cacheDirPath: string }) {
|
||||
export function downloadAndUnzip(params: {
|
||||
isSilent: boolean;
|
||||
url: string;
|
||||
destDirPath: string;
|
||||
pathOfDirToExtractInArchive?: string;
|
||||
cacheDirPath: string;
|
||||
}) {
|
||||
const { url, destDirPath, pathOfDirToExtractInArchive, cacheDirPath } = params;
|
||||
|
||||
const extractDirPath = pathJoin(
|
||||
@ -54,7 +60,7 @@ export function downloadAndUnzip(params: { url: string; destDirPath: string; pat
|
||||
|
||||
const zipFileBasename = pathBasename(url);
|
||||
|
||||
execSync(`curl -L ${url} -o ${zipFileBasename}`, { "cwd": extractDirPath });
|
||||
execSync(`curl -L ${url} -o ${zipFileBasename} ${params.isSilent ? "-s" : ""}`, { "cwd": extractDirPath });
|
||||
|
||||
execSync(`unzip -o ${zipFileBasename}${pathOfDirToExtractInArchive === undefined ? "" : ` "${pathOfDirToExtractInArchive}/**/*"`}`, {
|
||||
"cwd": extractDirPath
|
||||
|
27
src/bin/tools/logger.ts
Normal file
27
src/bin/tools/logger.ts
Normal file
@ -0,0 +1,27 @@
|
||||
type LoggerOpts = {
|
||||
force?: boolean;
|
||||
};
|
||||
|
||||
type Logger = {
|
||||
log: (message: string, opts?: LoggerOpts) => void;
|
||||
warn: (message: string) => void;
|
||||
error: (message: string) => void;
|
||||
};
|
||||
|
||||
export const getLogger = ({ isSilent }: { isSilent?: boolean } = {}): Logger => {
|
||||
return {
|
||||
log: (message, { force } = {}) => {
|
||||
if (isSilent && !force) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(message);
|
||||
},
|
||||
warn: message => {
|
||||
console.warn(message);
|
||||
},
|
||||
error: message => {
|
||||
console.error(message);
|
||||
}
|
||||
};
|
||||
};
|
@ -83,8 +83,6 @@ export function __unsafe_useI18n<ExtraMessageKey extends string = never>(params:
|
||||
return;
|
||||
}
|
||||
|
||||
let isMounted = true;
|
||||
|
||||
refHasStartedFetching.current = true;
|
||||
|
||||
(async () => {
|
||||
@ -144,10 +142,6 @@ export function __unsafe_useI18n<ExtraMessageKey extends string = never>(params:
|
||||
})()
|
||||
]).then(modules => modules.map(module => module.default));
|
||||
|
||||
if (!isMounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
setI18n({
|
||||
...createI18nTranslationFunctions({
|
||||
"fallbackMessages": {
|
||||
@ -180,10 +174,6 @@ export function __unsafe_useI18n<ExtraMessageKey extends string = never>(params:
|
||||
)
|
||||
});
|
||||
})();
|
||||
|
||||
return () => {
|
||||
isMounted = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
return i18n ?? null;
|
||||
|
@ -14,6 +14,7 @@ generateKeycloakThemeResources({
|
||||
"extraPages": ["my-custom-page.ftl"],
|
||||
"extraThemeProperties": ["env=test"],
|
||||
"isStandalone": true,
|
||||
"urlPathname": "/keycloakify-demo-app/"
|
||||
"urlPathname": "/keycloakify-demo-app/",
|
||||
"isSilent": false
|
||||
}
|
||||
});
|
||||
|
@ -19,7 +19,7 @@ import { assetIsSameCode } from "../tools/assertIsSameCode";
|
||||
}[e] + ".chunk.js"
|
||||
}
|
||||
|
||||
n.u=function(e){return"static/js/" + e + "." + {
|
||||
__webpack_require__.u=function(e){return"static/js/" + e + "." + {
|
||||
147: "6c5cee76",
|
||||
787: "8da10fcf",
|
||||
922: "be170a73"
|
||||
@ -54,10 +54,10 @@ import { assetIsSameCode } from "../tools/assertIsSameCode";
|
||||
}[e] + ".chunk.js"
|
||||
}
|
||||
|
||||
n[(function (){
|
||||
var pd= Object.getOwnPropertyDescriptor(n, "p");
|
||||
__webpack_require__[(function (){
|
||||
var pd= Object.getOwnPropertyDescriptor(__webpack_require__, "p");
|
||||
if( pd === undefined || pd.configurable ){
|
||||
Object.defineProperty(n, "p", {
|
||||
Object.defineProperty(__webpack_require__, "p", {
|
||||
get: function() { return window.kcContext.url.resourcesPath; },
|
||||
set: function (){}
|
||||
});
|
||||
@ -72,7 +72,7 @@ import { assetIsSameCode } from "../tools/assertIsSameCode";
|
||||
}
|
||||
|
||||
t[(function (){
|
||||
var pd= Object.getOwnPropertyDescriptor(n, "p");
|
||||
var pd= Object.getOwnPropertyDescriptor(t, "p");
|
||||
if( pd === undefined || pd.configurable ){
|
||||
Object.defineProperty(t, "p", {
|
||||
get: function() { return window.kcContext.url.resourcesPath; },
|
||||
@ -103,23 +103,23 @@ import { assetIsSameCode } from "../tools/assertIsSameCode";
|
||||
|
||||
const fixedJsCodeExpected = `
|
||||
function f() {
|
||||
return ("kcContext" in window ? "https://demo-app.keycloakify.dev" : "") + a.p + "static/js/" + ({}[e] || e) + "." + {
|
||||
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) + "." + {
|
||||
return ("kcContext" in window ? "https://demo-app.keycloakify.dev/" : a.p) + "static/js/" + ({}[e] || e) + "." + {
|
||||
3: "0664cdc0"
|
||||
}[e] + ".chunk.js"
|
||||
}
|
||||
|
||||
n[(function (){
|
||||
var pd= Object.getOwnPropertyDescriptor(n, "p");
|
||||
__webpack_require__[(function (){
|
||||
var pd= Object.getOwnPropertyDescriptor(__webpack_require__, "p");
|
||||
if( pd === undefined || pd.configurable ){
|
||||
var p= "";
|
||||
Object.defineProperty(n, "p", {
|
||||
get: function() { return ("kcContext" in window ? "https://demo-app.keycloakify.dev" : "") + p; },
|
||||
Object.defineProperty(__webpack_require__, "p", {
|
||||
get: function() { return "kcContext" in window ? "https://demo-app.keycloakify.dev/" : p; },
|
||||
set: function (value){ p = value; }
|
||||
});
|
||||
}
|
||||
@ -133,11 +133,11 @@ import { assetIsSameCode } from "../tools/assertIsSameCode";
|
||||
}
|
||||
|
||||
t[(function (){
|
||||
var pd= Object.getOwnPropertyDescriptor(n, "p");
|
||||
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; },
|
||||
get: function() { return "kcContext" in window ? "https://demo-app.keycloakify.dev/" : p; },
|
||||
set: function (value){ p = value; }
|
||||
});
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ export function setupSampleReactProject() {
|
||||
downloadAndUnzip({
|
||||
"url": "https://github.com/InseeFrLab/keycloakify/releases/download/v0.0.1/sample_build_dir_and_package_json.zip",
|
||||
"destDirPath": sampleReactProjectDirPath,
|
||||
"cacheDirPath": pathJoin(sampleReactProjectDirPath, "build_keycloak", ".cache")
|
||||
"cacheDirPath": pathJoin(sampleReactProjectDirPath, "build_keycloak", ".cache"),
|
||||
"isSilent": false
|
||||
});
|
||||
}
|
||||
|
18
yarn.lock
18
yarn.lock
@ -265,6 +265,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/memoizee/-/memoizee-0.4.8.tgz#04adc0c266a0f5d72db0556fdda2ba17dad9b519"
|
||||
integrity sha512-qDpXKGgwKywnQt/64fH1O0LiPA++QGIYeykEUiZ51HymKVRLnUSGcRuF60IfpPeeXiuRwiR/W4y7S5VzbrgLCA==
|
||||
|
||||
"@types/minimist@^1.2.2":
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c"
|
||||
integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==
|
||||
|
||||
"@types/node@^17.0.25":
|
||||
version "17.0.45"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190"
|
||||
@ -1188,6 +1193,11 @@ minimatch@^3.0.3, minimatch@^3.1.1:
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.6:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
|
||||
|
||||
mkdirp@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||
@ -1733,10 +1743,10 @@ tslib@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
|
||||
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
|
||||
|
||||
tss-react@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/tss-react/-/tss-react-4.0.0.tgz#cdd9d4c4ae24de04c13b9deff59b50fdf6ce10ae"
|
||||
integrity sha512-pPkOKWiWWPbKdQFnGGeHEgRceUwkjrv0eldVCAdBll3j6Y3Ys/xwqsnlWYwWOU3SMJygVRE/S4CsIYx6KPpOkA==
|
||||
tss-react@^4.1.3:
|
||||
version "4.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tss-react/-/tss-react-4.1.3.tgz#170a2edd85e32ba3b752416eeb45438c35e90243"
|
||||
integrity sha512-Ul99aVoVngHY2nwFC87jZlGP+K3LfG9ZRakimOzRwgJz77f/zXWuY2FVzwaSc+OW804twNaxZZRtLlpagex8sg==
|
||||
dependencies:
|
||||
"@emotion/cache" "*"
|
||||
"@emotion/serialize" "*"
|
||||
|
Reference in New Issue
Block a user