Compare commits

..

6 Commits

Author SHA1 Message Date
c323b94a8c Bump version 2024-12-04 00:09:14 +01:00
4bbc0241ec Do not crash when parser can't be inferred 2024-12-04 00:04:49 +01:00
5a7dacfcdd Bump version 2024-12-02 00:41:30 +01:00
7e05e1bf0c Use random port for dev server 2024-12-02 00:41:12 +01:00
1530ca32c8 Bump version 2024-12-01 00:07:28 +01:00
ed054f131a Merge pull request #736 from keycloakify/hmr_in_start_keycloak
Implement hot module replacement for developing Account SPA and Admin UI
2024-12-01 00:01:57 +01:00
6 changed files with 54 additions and 21 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "keycloakify", "name": "keycloakify",
"version": "11.3.32", "version": "11.4.2",
"description": "Framework to create custom Keycloak UIs", "description": "Framework to create custom Keycloak UIs",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -11,7 +11,11 @@ import * as fs from "fs";
import { join as pathJoin } from "path"; import { join as pathJoin } from "path";
import type { BuildContext } from "../../shared/buildContext"; import type { BuildContext } from "../../shared/buildContext";
import { assert } from "tsafe/assert"; import { assert } from "tsafe/assert";
import { type ThemeType, WELL_KNOWN_DIRECTORY_BASE_NAME } from "../../shared/constants"; import {
type ThemeType,
WELL_KNOWN_DIRECTORY_BASE_NAME,
KEYCLOAKIFY_SPA_DEV_SERVER_PORT
} from "../../shared/constants";
import { getThisCodebaseRootDirPath } from "../../tools/getThisCodebaseRootDirPath"; import { getThisCodebaseRootDirPath } from "../../tools/getThisCodebaseRootDirPath";
export type BuildContextLike = BuildContextLike_replaceImportsInJsCode & export type BuildContextLike = BuildContextLike_replaceImportsInJsCode &
@ -116,6 +120,7 @@ export function generateFtlFilesCodeFactory(params: {
.replace("{{themeVersion}}", buildContext.themeVersion) .replace("{{themeVersion}}", buildContext.themeVersion)
.replace("{{fieldNames}}", fieldNames.map(name => `"${name}"`).join(", ")) .replace("{{fieldNames}}", fieldNames.map(name => `"${name}"`).join(", "))
.replace("{{RESOURCES_COMMON}}", WELL_KNOWN_DIRECTORY_BASE_NAME.RESOURCES_COMMON) .replace("{{RESOURCES_COMMON}}", WELL_KNOWN_DIRECTORY_BASE_NAME.RESOURCES_COMMON)
.replace("{{KEYCLOAKIFY_SPA_DEV_SERVER_PORT}}", KEYCLOAKIFY_SPA_DEV_SERVER_PORT)
.replace( .replace(
"{{userDefinedExclusions}}", "{{userDefinedExclusions}}",
buildContext.kcContextExclusionsFtlCode ?? "" buildContext.kcContextExclusionsFtlCode ?? ""

View File

@ -101,7 +101,7 @@ redirect_to_dev_server: {
break redirect_to_dev_server; break redirect_to_dev_server;
} }
const devSeverPort = kcContext.properties.KEYCLOAKIFY_SPA_DEV_SERVER_PORT; const devSeverPort = kcContext.properties.{{KEYCLOAKIFY_SPA_DEV_SERVER_PORT}};
if( !devSeverPort ){ if( !devSeverPort ){
break redirect_to_dev_server; break redirect_to_dev_server;
@ -115,7 +115,7 @@ redirect_to_dev_server: {
console.log(kcContext); console.log(kcContext);
redirectUrl.searchParams.set("kcContext", encodeURIComponent(JSON.stringify(kcContext)) ); redirectUrl.searchParams.set("kcContext", encodeURIComponent(JSON.stringify(kcContext)));
window.location.href = redirectUrl.toString(); window.location.href = redirectUrl.toString();

View File

@ -380,14 +380,14 @@ export async function command(params: {
const port = const port =
cliCommandOptions.port ?? buildContext.startKeycloakOptions.port ?? DEFAULT_PORT; cliCommandOptions.port ?? buildContext.startKeycloakOptions.port ?? DEFAULT_PORT;
const devServerPort = (() => { const doStartDevServer = (() => {
const hasSpaUi = const hasSpaUi =
buildContext.implementedThemeTypes.admin.isImplemented || buildContext.implementedThemeTypes.admin.isImplemented ||
(buildContext.implementedThemeTypes.account.isImplemented && (buildContext.implementedThemeTypes.account.isImplemented &&
buildContext.implementedThemeTypes.account.type === "Single-Page"); buildContext.implementedThemeTypes.account.type === "Single-Page");
if (!hasSpaUi) { if (!hasSpaUi) {
return undefined; return false;
} }
if (buildContext.bundler !== "vite") { if (buildContext.bundler !== "vite") {
@ -401,7 +401,7 @@ export async function command(params: {
) )
); );
return undefined; return false;
} }
if (keycloakMajorVersionNumber < 25) { if (keycloakMajorVersionNumber < 25) {
@ -415,17 +415,18 @@ export async function command(params: {
) )
); );
return undefined; return false;
} }
return port + 1; return true;
})(); })();
if (devServerPort !== undefined) { let devServerPort: number | undefined = undefined;
startViteDevServer({
buildContext, if (doStartDevServer) {
port: devServerPort const { port } = await startViteDevServer({ buildContext });
});
devServerPort = port;
} }
const SPACE_PLACEHOLDER = "SPACE_PLACEHOLDER_xKLmdPd"; const SPACE_PLACEHOLDER = "SPACE_PLACEHOLDER_xKLmdPd";

View File

@ -3,6 +3,7 @@ import { assert } from "tsafe/assert";
import type { BuildContext } from "../shared/buildContext"; import type { BuildContext } from "../shared/buildContext";
import chalk from "chalk"; import chalk from "chalk";
import { VITE_PLUGIN_SUB_SCRIPTS_ENV_NAMES } from "../shared/constants"; import { VITE_PLUGIN_SUB_SCRIPTS_ENV_NAMES } from "../shared/constants";
import { Deferred } from "evt/tools/Deferred";
export type BuildContextLike = { export type BuildContextLike = {
projectDirPath: string; projectDirPath: string;
@ -12,13 +13,12 @@ assert<BuildContext extends BuildContextLike ? true : false>();
export function startViteDevServer(params: { export function startViteDevServer(params: {
buildContext: BuildContextLike; buildContext: BuildContextLike;
port: number; }): Promise<{ port: number }> {
}): void { const { buildContext } = params;
const { buildContext, port } = params;
console.log(chalk.blue(`$ npx vite dev --port ${port}`)); console.log(chalk.blue(`$ npx vite dev`));
const child = child_process.spawn("npx", ["vite", "dev", "--port", `${port}`], { const child = child_process.spawn("npx", ["vite", "dev"], {
cwd: buildContext.projectDirPath, cwd: buildContext.projectDirPath,
env: { env: {
...process.env, ...process.env,
@ -36,4 +36,31 @@ export function startViteDevServer(params: {
}); });
child.stderr.on("data", data => process.stderr.write(data)); child.stderr.on("data", data => process.stderr.write(data));
const dPort = new Deferred<number>();
{
const onData = (data: Buffer) => {
//Local: http://localhost:8083/
const match = data
.toString("utf8")
.match(/Local:\s*http:\/\/(?:localhost|127\.0\.0\.1):(\d+)\//);
if (match === null) {
return;
}
child.stdout.off("data", onData);
const port = parseInt(match[1]);
assert(!isNaN(port));
dPort.resolve(port);
};
child.stdout.on("data", onData);
}
return dPort.pr.then(port => ({ port }));
} }

View File

@ -101,7 +101,7 @@ export async function runPrettier(params: {
resolveConfig: true resolveConfig: true
}); });
if (ignored) { if (ignored || inferredParser === null) {
return sourceCode; return sourceCode;
} }
@ -110,7 +110,7 @@ export async function runPrettier(params: {
formattedSourceCode = await prettier.format(sourceCode, { formattedSourceCode = await prettier.format(sourceCode, {
...config, ...config,
filePath, filePath,
parser: inferredParser ?? undefined parser: inferredParser
}); });
} catch (error) { } catch (error) {
console.log( console.log(