Compare commits
19 Commits
v10.0.0-rc
...
bundle_jar
Author | SHA1 | Date | |
---|---|---|---|
7d8ae040fd | |||
c6cf564842 | |||
380b739017 | |||
c3f3c55303 | |||
2c01018529 | |||
dd2edf3013 | |||
7f3cdf9fac | |||
f75a91fbc1 | |||
f151086bb1 | |||
7c833e6f10 | |||
885e8314e8 | |||
3bdd955ab6 | |||
9499587bad | |||
0879ddba7c | |||
106a1dd4c7 | |||
5580248bcd | |||
c9c10b8fba | |||
ed254922e9 | |||
4b7d1e2cec |
@ -240,6 +240,15 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "oliviergoulet5",
|
||||
"name": "Olivier Goulet",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/17685861?v=4",
|
||||
"profile": "https://github.com/oliviergoulet5",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
@ -132,6 +132,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/law108000"><img src="https://avatars.githubusercontent.com/u/8112024?v=4?s=100" width="100px;" alt="Rlok"/><br /><sub><b>Rlok</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/commits?author=law108000" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Moulyy"><img src="https://avatars.githubusercontent.com/u/115405804?v=4?s=100" width="100px;" alt="Moulyy"/><br /><sub><b>Moulyy</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/commits?author=Moulyy" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/madmadson"><img src="https://avatars.githubusercontent.com/u/798831?v=4?s=100" width="100px;" alt="Tobias Matt"/><br /><sub><b>Tobias Matt</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/commits?author=madmadson" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/oliviergoulet5"><img src="https://avatars.githubusercontent.com/u/17685861?v=4?s=100" width="100px;" alt="Olivier Goulet"/><br /><sub><b>Olivier Goulet</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/commits?author=oliviergoulet5" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "keycloakify",
|
||||
"version": "10.0.0-rc.140",
|
||||
"version": "10.0.0-rc.147",
|
||||
"description": "Create Keycloak themes using React",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -17,15 +17,20 @@ import { isInside } from "../../tools/isInside";
|
||||
import child_process from "child_process";
|
||||
import { rmSync } from "../../tools/fs.rmSync";
|
||||
import { writeMetaInfKeycloakThemes } from "../../shared/metaInfKeycloakThemes";
|
||||
import {
|
||||
bundleExtensionsIntoJar,
|
||||
type BuildContextLike as BuildContextLike_bundleExtensionsIntoJar
|
||||
} from "./bundleExtensionsIntoJar";
|
||||
|
||||
export type BuildContextLike = BuildContextLike_generatePom & {
|
||||
keycloakifyBuildDirPath: string;
|
||||
themeNames: string[];
|
||||
artifactId: string;
|
||||
themeVersion: string;
|
||||
cacheDirPath: string;
|
||||
implementedThemeTypes: BuildContext["implementedThemeTypes"];
|
||||
};
|
||||
export type BuildContextLike = BuildContextLike_generatePom &
|
||||
BuildContextLike_bundleExtensionsIntoJar & {
|
||||
keycloakifyBuildDirPath: string;
|
||||
themeNames: string[];
|
||||
artifactId: string;
|
||||
themeVersion: string;
|
||||
cacheDirPath: string;
|
||||
implementedThemeTypes: BuildContext["implementedThemeTypes"];
|
||||
};
|
||||
|
||||
assert<BuildContext extends BuildContextLike ? true : false>();
|
||||
|
||||
@ -234,12 +239,19 @@ export async function buildJar(params: {
|
||||
)
|
||||
);
|
||||
|
||||
const jarFilePath_generatedByMaven = pathJoin(
|
||||
keycloakifyBuildCacheDirPath,
|
||||
"target",
|
||||
`${buildContext.artifactId}-${buildContext.themeVersion}.jar`
|
||||
);
|
||||
|
||||
await bundleExtensionsIntoJar({
|
||||
buildContext,
|
||||
jarFilePath: jarFilePath_generatedByMaven
|
||||
});
|
||||
|
||||
await fs.rename(
|
||||
pathJoin(
|
||||
keycloakifyBuildCacheDirPath,
|
||||
"target",
|
||||
`${buildContext.artifactId}-${buildContext.themeVersion}.jar`
|
||||
),
|
||||
jarFilePath_generatedByMaven,
|
||||
pathJoin(buildContext.keycloakifyBuildDirPath, jarFileBasename)
|
||||
);
|
||||
}
|
||||
|
137
src/bin/keycloakify/buildJars/bundleExtensionsIntoJar.ts
Normal file
137
src/bin/keycloakify/buildJars/bundleExtensionsIntoJar.ts
Normal file
@ -0,0 +1,137 @@
|
||||
import { downloadAndExtractArchive } from "../../tools/downloadAndExtractArchive";
|
||||
import { assert } from "tsafe/assert";
|
||||
import type { BuildContext } from "../../shared/buildContext";
|
||||
import { transformCodebase } from "../../tools/transformCodebase";
|
||||
import { join as pathJoin, basename as pathBasename, sep as pathSep } from "path";
|
||||
import { rm } from "../../tools/fs.rm";
|
||||
import { extractArchive } from "../../tools/extractArchive";
|
||||
import * as crypto from "crypto";
|
||||
|
||||
export type BuildContextLike = {
|
||||
cacheDirPath: string;
|
||||
fetchOptions: BuildContext["fetchOptions"];
|
||||
extensionJars: BuildContext["extensionJars"];
|
||||
};
|
||||
|
||||
assert<BuildContext extends BuildContextLike ? true : false>();
|
||||
|
||||
export async function bundleExtensionsIntoJar(params: {
|
||||
jarFilePath: string;
|
||||
buildContext: BuildContextLike;
|
||||
}): Promise<void> {
|
||||
const { jarFilePath, buildContext } = params;
|
||||
|
||||
if (buildContext.extensionJars.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mergeDirPath = pathJoin(
|
||||
buildContext.cacheDirPath,
|
||||
`merge_${pathBasename(jarFilePath).replace(/\.jar$/, "")}_${crypto
|
||||
.createHash("sha256")
|
||||
.update(jarFilePath)
|
||||
.digest("hex")
|
||||
.substring(0, 5)}`
|
||||
);
|
||||
|
||||
await extractArchive({
|
||||
archiveFilePath: jarFilePath,
|
||||
onArchiveFile: async ({ relativeFilePathInArchive, writeFile }) =>
|
||||
writeFile({
|
||||
filePath: pathJoin(mergeDirPath, relativeFilePathInArchive)
|
||||
})
|
||||
});
|
||||
|
||||
for (const extensionJar of buildContext.extensionJars) {
|
||||
const transformSourceCode = (params: {
|
||||
fileRelativePath: string;
|
||||
sourceCode: Buffer;
|
||||
}): { modifiedSourceCode: Buffer } | undefined => {
|
||||
const { fileRelativePath } = params;
|
||||
|
||||
if (!fileRelativePath.startsWith(`META-INF${pathSep}`)) {
|
||||
for (const ext of [".DSA", ".SF", ".RSA"]) {
|
||||
if (fileRelativePath.endsWith(ext)) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
switch (extensionJar.type) {
|
||||
case "path":
|
||||
await extractArchive({
|
||||
archiveFilePath: extensionJar.path,
|
||||
onArchiveFile: async ({
|
||||
relativeFilePathInArchive,
|
||||
writeFile,
|
||||
readFile
|
||||
}) => {
|
||||
const transformResult = transformSourceCode({
|
||||
fileRelativePath: relativeFilePathInArchive,
|
||||
sourceCode: await readFile()
|
||||
});
|
||||
|
||||
if (transformResult === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
await writeFile({
|
||||
filePath: pathJoin(mergeDirPath, relativeFilePathInArchive),
|
||||
modifiedData: transformResult.modifiedSourceCode
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
case "url": {
|
||||
const { extractedDirPath } = await downloadAndExtractArchive({
|
||||
url: extensionJar.url,
|
||||
cacheDirPath: buildContext.cacheDirPath,
|
||||
fetchOptions: buildContext.fetchOptions,
|
||||
uniqueIdOfOnArchiveFile: "noOp",
|
||||
onArchiveFile: async ({ fileRelativePath, writeFile }) =>
|
||||
writeFile({ fileRelativePath })
|
||||
});
|
||||
transformCodebase({
|
||||
srcDirPath: extractedDirPath,
|
||||
destDirPath: mergeDirPath,
|
||||
transformSourceCode
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
transformCodebase({
|
||||
srcDirPath: extractedDirPath,
|
||||
destDirPath: mergeDirPath,
|
||||
transformSourceCode: ({ fileRelativePath, sourceCode }) => {
|
||||
if (fileRelativePath === pathJoin("META-INF", "MANIFEST.MF")) {
|
||||
const sourceCodeStr = sourceCode.toString("utf8");
|
||||
|
||||
const lines = sourceCodeStr.split(/\r?\n/);
|
||||
|
||||
console.log(lines);
|
||||
|
||||
return {
|
||||
modifiedSourceCode: Buffer.concat([
|
||||
sourceCode,
|
||||
Buffer.from(
|
||||
`Class-Path: ${pathBasename(userProvidedJarFilePathOrUrl)}\n`
|
||||
)
|
||||
])
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
// TODO: Acctually build new jar
|
||||
|
||||
await rm(mergeDirPath, { recursive: true, force: true });
|
||||
}
|
@ -314,7 +314,7 @@ export async function generateResourcesForMainTheme(params: {
|
||||
}
|
||||
|
||||
const { extractedDirPath } = await downloadAndExtractArchive({
|
||||
urlOrPath: "https://repo1.maven.org/maven2/org/keycloak/keycloak-account-ui/25.0.1/keycloak-account-ui-25.0.1.jar",
|
||||
url: "https://repo1.maven.org/maven2/org/keycloak/keycloak-account-ui/25.0.1/keycloak-account-ui-25.0.1.jar",
|
||||
cacheDirPath: buildContext.cacheDirPath,
|
||||
fetchOptions: buildContext.fetchOptions,
|
||||
uniqueIdOfOnArchiveFile: "bring_in_account_v3_i18n_messages",
|
||||
|
@ -26,6 +26,8 @@ import { type ThemeType } from "./constants";
|
||||
import { id } from "tsafe/id";
|
||||
import chalk from "chalk";
|
||||
import { getProxyFetchOptions, type ProxyFetchOptions } from "../tools/fetchProxyOptions";
|
||||
import { removeDuplicates } from "evt/tools/reducers/removeDuplicates";
|
||||
import { same } from "evt/tools/inDepth/same";
|
||||
|
||||
export type BuildContext = {
|
||||
themeVersion: string;
|
||||
@ -61,6 +63,7 @@ export type BuildContext = {
|
||||
keycloakVersionRange: KeycloakVersionRange;
|
||||
jarFileBasename: string;
|
||||
}[];
|
||||
extensionJars: ({ type: "path"; path: string } | { type: "url"; url: string })[];
|
||||
startKeycloakOptions: {
|
||||
dockerImage:
|
||||
| {
|
||||
@ -88,6 +91,7 @@ export type BuildOptions = {
|
||||
loginThemeResourcesFromKeycloakVersion?: string;
|
||||
keycloakifyBuildDirPath?: string;
|
||||
kcContextExclusionsFtl?: string;
|
||||
extensionJars?: string[];
|
||||
startKeycloakOptions?: {
|
||||
dockerImage?: string;
|
||||
dockerExtraArgs?: string[];
|
||||
@ -360,6 +364,7 @@ export function getBuildContext(params: {
|
||||
loginThemeResourcesFromKeycloakVersion: z.string().optional(),
|
||||
keycloakifyBuildDirPath: z.string().optional(),
|
||||
kcContextExclusionsFtl: z.string().optional(),
|
||||
extensionJars: z.array(z.string()).optional(),
|
||||
startKeycloakOptions: zStartKeycloakOptions.optional()
|
||||
}),
|
||||
zAccountThemeImplAndKeycloakVersionTargets
|
||||
@ -520,6 +525,36 @@ export function getBuildContext(params: {
|
||||
return pathJoin(projectDirPath, resolvedViteConfig.buildDir);
|
||||
})();
|
||||
|
||||
const buildForKeycloakMajorVersionNumber = (() => {
|
||||
const envValue = process.env[BUILD_FOR_KEYCLOAK_MAJOR_VERSION_ENV_NAME];
|
||||
|
||||
if (envValue === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const major = parseInt(envValue);
|
||||
|
||||
assert(!isNaN(major));
|
||||
|
||||
return major;
|
||||
})();
|
||||
|
||||
function urlOrPathToDiscriminatingWrapper(
|
||||
urlOrPath: string
|
||||
): { type: "url"; url: string } | { type: "path"; path: string } {
|
||||
if (/^https?:\/\//.test(urlOrPath)) {
|
||||
return { type: "url", url: urlOrPath };
|
||||
}
|
||||
|
||||
return {
|
||||
type: "path",
|
||||
path: getAbsoluteAndInOsFormatPath({
|
||||
pathIsh: urlOrPath,
|
||||
cwd: projectDirPath
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
bundler,
|
||||
packageJsonFilePath,
|
||||
@ -717,21 +752,6 @@ export function getBuildContext(params: {
|
||||
`keycloak-theme-for-kc-${range}.jar`;
|
||||
|
||||
build_for_specific_keycloak_major_version: {
|
||||
const buildForKeycloakMajorVersionNumber = (() => {
|
||||
const envValue =
|
||||
process.env[BUILD_FOR_KEYCLOAK_MAJOR_VERSION_ENV_NAME];
|
||||
|
||||
if (envValue === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const major = parseInt(envValue);
|
||||
|
||||
assert(!isNaN(major));
|
||||
|
||||
return major;
|
||||
})();
|
||||
|
||||
if (buildForKeycloakMajorVersionNumber === undefined) {
|
||||
break build_for_specific_keycloak_major_version;
|
||||
}
|
||||
@ -931,6 +951,10 @@ export function getBuildContext(params: {
|
||||
|
||||
return jarTargets;
|
||||
})(),
|
||||
extensionJars: (buildForKeycloakMajorVersionNumber !== undefined
|
||||
? []
|
||||
: buildOptions.extensionJars ?? []
|
||||
).map(urlOrPath => urlOrPathToDiscriminatingWrapper(urlOrPath)),
|
||||
startKeycloakOptions: {
|
||||
dockerImage: (() => {
|
||||
if (buildOptions.startKeycloakOptions?.dockerImage === undefined) {
|
||||
@ -949,21 +973,14 @@ export function getBuildContext(params: {
|
||||
})(),
|
||||
dockerExtraArgs: buildOptions.startKeycloakOptions?.dockerExtraArgs ?? [],
|
||||
keycloakExtraArgs: buildOptions.startKeycloakOptions?.keycloakExtraArgs ?? [],
|
||||
extensionJars: (buildOptions.startKeycloakOptions?.extensionJars ?? []).map(
|
||||
urlOrPath => {
|
||||
if (/^https?:\/\//.test(urlOrPath)) {
|
||||
return { type: "url", url: urlOrPath };
|
||||
}
|
||||
|
||||
return {
|
||||
type: "path",
|
||||
path: getAbsoluteAndInOsFormatPath({
|
||||
pathIsh: urlOrPath,
|
||||
cwd: projectDirPath
|
||||
})
|
||||
};
|
||||
}
|
||||
),
|
||||
extensionJars: [
|
||||
...(buildForKeycloakMajorVersionNumber !== undefined
|
||||
? buildOptions.extensionJars ?? []
|
||||
: []),
|
||||
...(buildOptions.startKeycloakOptions?.extensionJars ?? [])
|
||||
]
|
||||
.map(urlOrPath => urlOrPathToDiscriminatingWrapper(urlOrPath))
|
||||
.reduce(...removeDuplicates<BuildContext["extensionJars"][number]>(same)),
|
||||
realmJsonFilePath:
|
||||
buildOptions.startKeycloakOptions?.realmJsonFilePath === undefined
|
||||
? undefined
|
||||
|
@ -21,7 +21,7 @@ export async function downloadKeycloakDefaultTheme(params: {
|
||||
let kcNodeModulesKeepFilePaths_lastAccountV1: Set<string> | undefined = undefined;
|
||||
|
||||
const { extractedDirPath } = await downloadAndExtractArchive({
|
||||
urlOrPath: `https://repo1.maven.org/maven2/org/keycloak/keycloak-themes/${keycloakVersion}/keycloak-themes-${keycloakVersion}.jar`,
|
||||
url: `https://repo1.maven.org/maven2/org/keycloak/keycloak-themes/${keycloakVersion}/keycloak-themes-${keycloakVersion}.jar`,
|
||||
cacheDirPath: buildContext.cacheDirPath,
|
||||
fetchOptions: buildContext.fetchOptions,
|
||||
uniqueIdOfOnArchiveFile: "downloadKeycloakDefaultTheme",
|
||||
|
@ -55,7 +55,7 @@ export async function promptKeycloakVersion(params: {
|
||||
});
|
||||
|
||||
const lastMajorVersions = Array.from(semVersionedTagByMajor.values()).map(
|
||||
({ tag }) => tag
|
||||
({ version }) => `${version.major}.${version.minor}`
|
||||
);
|
||||
|
||||
const { value } = await cliSelect<string>({
|
||||
|
@ -200,7 +200,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
|
||||
const { archiveFilePath } = await downloadAndExtractArchive({
|
||||
cacheDirPath: buildContext.cacheDirPath,
|
||||
fetchOptions: buildContext.fetchOptions,
|
||||
urlOrPath: extensionJar.url,
|
||||
url: extensionJar.url,
|
||||
uniqueIdOfOnArchiveFile: "no extraction",
|
||||
onArchiveFile: async () => {}
|
||||
});
|
||||
@ -334,19 +334,30 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
|
||||
});
|
||||
} catch {}
|
||||
|
||||
const DEFAULT_PORT = 8080;
|
||||
const port =
|
||||
cliCommandOptions.port ?? buildContext.startKeycloakOptions.port ?? DEFAULT_PORT;
|
||||
|
||||
const SPACE_PLACEHOLDER = "SPACE_PLACEHOLDER_xKLmdPd";
|
||||
|
||||
const dockerRunArgs: string[] = [
|
||||
`-p${SPACE_PLACEHOLDER}${cliCommandOptions.port ?? buildContext.startKeycloakOptions.port ?? 8080}:8080`,
|
||||
`-p${SPACE_PLACEHOLDER}${port}:8080`,
|
||||
`--name${SPACE_PLACEHOLDER}${CONTAINER_NAME}`,
|
||||
`-e${SPACE_PLACEHOLDER}KEYCLOAK_ADMIN=admin`,
|
||||
`-e${SPACE_PLACEHOLDER}KEYCLOAK_ADMIN_PASSWORD=admin`,
|
||||
...(buildContext.startKeycloakOptions.dockerExtraArgs.length === 0
|
||||
? []
|
||||
: [
|
||||
buildContext.startKeycloakOptions.dockerExtraArgs.join(
|
||||
SPACE_PLACEHOLDER
|
||||
)
|
||||
]),
|
||||
...(realmJsonFilePath === undefined
|
||||
? []
|
||||
: [
|
||||
`-v${SPACE_PLACEHOLDER}".${pathSep}${pathRelative(process.cwd(), realmJsonFilePath)}":/opt/keycloak/data/import/myrealm-realm.json`
|
||||
]),
|
||||
`-v${SPACE_PLACEHOLDER}"./${pathRelative(process.cwd(), jarFilePath_cacheDir)}":/opt/keycloak/providers/keycloak-theme.jar`,
|
||||
`-v${SPACE_PLACEHOLDER}".${pathSep}${pathRelative(process.cwd(), jarFilePath_cacheDir)}":/opt/keycloak/providers/keycloak-theme.jar`,
|
||||
...extensionJarFilePaths.map(
|
||||
jarFilePath =>
|
||||
`-v${SPACE_PLACEHOLDER}".${pathSep}${pathRelative(process.cwd(), jarFilePath)}":/opt/keycloak/providers/${pathBasename(jarFilePath)}`
|
||||
@ -388,14 +399,19 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
|
||||
({ name, envValue }) =>
|
||||
`--env${SPACE_PLACEHOLDER}${name}='${envValue.replace(/'/g, "'\\''")}'`
|
||||
),
|
||||
...buildContext.startKeycloakOptions.dockerExtraArgs.join(SPACE_PLACEHOLDER),
|
||||
`${buildContext.startKeycloakOptions.dockerImage?.reference ?? "quay.io/keycloak/keycloak"}:${dockerImageTag}`,
|
||||
"start-dev",
|
||||
...(21 <= keycloakMajorVersionNumber && keycloakMajorVersionNumber < 24
|
||||
? ["--features=declarative-user-profile"]
|
||||
: []),
|
||||
...(realmJsonFilePath === undefined ? [] : ["--import-realm"]),
|
||||
...buildContext.startKeycloakOptions.keycloakExtraArgs.join(SPACE_PLACEHOLDER)
|
||||
...(buildContext.startKeycloakOptions.keycloakExtraArgs.length === 0
|
||||
? []
|
||||
: [
|
||||
buildContext.startKeycloakOptions.keycloakExtraArgs.join(
|
||||
SPACE_PLACEHOLDER
|
||||
)
|
||||
])
|
||||
];
|
||||
|
||||
console.log(
|
||||
@ -427,6 +443,18 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
|
||||
const srcDirPath = pathJoin(buildContext.projectDirPath, "src");
|
||||
|
||||
{
|
||||
const kcHttpRelativePath = (() => {
|
||||
const match = buildContext.startKeycloakOptions.dockerExtraArgs
|
||||
.join(" ")
|
||||
.match(/KC_HTTP_RELATIVE_PATH=([^ ]+)/);
|
||||
|
||||
if (match === null) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return match[1];
|
||||
})();
|
||||
|
||||
const handler = async (data: Buffer) => {
|
||||
if (!data.toString("utf8").includes("Listening on: http://0.0.0.0:8080")) {
|
||||
return;
|
||||
@ -444,7 +472,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
|
||||
)} are mounted in the Keycloak container.`,
|
||||
"",
|
||||
`Keycloak Admin console: ${chalk.cyan.bold(
|
||||
`http://localhost:${cliCommandOptions.port}`
|
||||
`http://localhost:${port}${kcHttpRelativePath ?? ""}`
|
||||
)}`,
|
||||
`- user: ${chalk.cyan.bold("admin")}`,
|
||||
`- password: ${chalk.cyan.bold("admin")}`,
|
||||
@ -452,7 +480,21 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
|
||||
"",
|
||||
`${chalk.green("Your theme is accessible at:")}`,
|
||||
`${chalk.green("➜")} ${chalk.cyan.bold(
|
||||
`https://my-theme.keycloakify.dev${cliCommandOptions.port === 8080 ? "" : `?port=${cliCommandOptions.port}`}`
|
||||
(() => {
|
||||
const url = new URL("https://my-theme.keycloakify.dev");
|
||||
|
||||
if (port !== DEFAULT_PORT) {
|
||||
url.searchParams.set("port", `${port}`);
|
||||
}
|
||||
if (kcHttpRelativePath !== undefined) {
|
||||
url.searchParams.set(
|
||||
"kcHttpRelativePath",
|
||||
kcHttpRelativePath
|
||||
);
|
||||
}
|
||||
|
||||
return url.href;
|
||||
})()
|
||||
)}`,
|
||||
"",
|
||||
"You can login with the following credentials:",
|
||||
|
@ -1,15 +1,14 @@
|
||||
import fetch, { type FetchOptions } from "make-fetch-happen";
|
||||
import { mkdir, unlink, writeFile, readdir, readFile } from "fs/promises";
|
||||
import { dirname as pathDirname, join as pathJoin, basename as pathBasename } from "path";
|
||||
import { dirname as pathDirname, join as pathJoin } from "path";
|
||||
import { assert } from "tsafe/assert";
|
||||
import { extractArchive } from "./extractArchive";
|
||||
import { existsAsync } from "./fs.existsAsync";
|
||||
import * as crypto from "crypto";
|
||||
import { rm } from "./fs.rm";
|
||||
import * as fsPr from "fs/promises";
|
||||
|
||||
export async function downloadAndExtractArchive(params: {
|
||||
urlOrPath: string;
|
||||
url: string;
|
||||
uniqueIdOfOnArchiveFile: string;
|
||||
onArchiveFile: (params: {
|
||||
fileRelativePath: string;
|
||||
@ -21,34 +20,17 @@ export async function downloadAndExtractArchive(params: {
|
||||
}) => Promise<void>;
|
||||
cacheDirPath: string;
|
||||
fetchOptions: FetchOptions | undefined;
|
||||
}): Promise<{ extractedDirPath: string; archiveFilePath: string; }> {
|
||||
const {
|
||||
urlOrPath,
|
||||
uniqueIdOfOnArchiveFile,
|
||||
onArchiveFile,
|
||||
cacheDirPath,
|
||||
fetchOptions
|
||||
} = params;
|
||||
}): Promise<{ extractedDirPath: string; archiveFilePath: string }> {
|
||||
const { url, uniqueIdOfOnArchiveFile, onArchiveFile, cacheDirPath, fetchOptions } =
|
||||
params;
|
||||
|
||||
const isUrl = /^https?:\/\//.test(urlOrPath);
|
||||
|
||||
const archiveFileBasename = isUrl
|
||||
? urlOrPath.split("?")[0].split("/").reverse()[0]
|
||||
: pathBasename(urlOrPath);
|
||||
const archiveFileBasename = url.split("?")[0].split("/").reverse()[0];
|
||||
|
||||
const archiveFilePath = pathJoin(cacheDirPath, archiveFileBasename);
|
||||
|
||||
download: {
|
||||
await mkdir(pathDirname(archiveFilePath), { recursive: true });
|
||||
|
||||
if (!isUrl) {
|
||||
await fsPr.copyFile(urlOrPath, archiveFilePath);
|
||||
|
||||
break download;
|
||||
}
|
||||
|
||||
const url = urlOrPath;
|
||||
|
||||
if (await existsAsync(archiveFilePath)) {
|
||||
const isDownloaded = await SuccessTracker.getIsDownloaded({
|
||||
cacheDirPath,
|
||||
|
@ -153,7 +153,7 @@ export default function WebauthnRegister(props: PageProps<Extract<KcContext, { p
|
||||
|
||||
function getPubKeyCredParams(signatureAlgorithmsList) {
|
||||
let pubKeyCredParams = [];
|
||||
if (signatureAlgorithmsList === []) {
|
||||
if (signatureAlgorithmsList.length === 0) {
|
||||
pubKeyCredParams.push({type: "public-key", alg: -7});
|
||||
return pubKeyCredParams;
|
||||
}
|
||||
@ -184,7 +184,7 @@ export default function WebauthnRegister(props: PageProps<Extract<KcContext, { p
|
||||
}
|
||||
|
||||
function getTransportsAsString(transportsList) {
|
||||
if (transportsList === '' || transportsList.constructor !== Array) return "";
|
||||
if (transportsList === '' || Array.isArray(transportsList)) return "";
|
||||
|
||||
let transportsString = "";
|
||||
|
||||
|
Reference in New Issue
Block a user