Rely on @keycloakify/email-native for email initialization
This commit is contained in:
parent
4845d7c32d
commit
fb2d651a6f
@ -23,22 +23,6 @@ export async function command(params: { buildContext: BuildContext }) {
|
|||||||
|
|
||||||
const accountThemeSrcDirPath = pathJoin(buildContext.themeSrcDirPath, "account");
|
const accountThemeSrcDirPath = pathJoin(buildContext.themeSrcDirPath, "account");
|
||||||
|
|
||||||
if (
|
|
||||||
fs.existsSync(accountThemeSrcDirPath) &&
|
|
||||||
fs.readdirSync(accountThemeSrcDirPath).length > 0
|
|
||||||
) {
|
|
||||||
console.warn(
|
|
||||||
chalk.red(
|
|
||||||
`There is already a ${pathRelative(
|
|
||||||
process.cwd(),
|
|
||||||
accountThemeSrcDirPath
|
|
||||||
)} directory in your project. Aborting.`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
process.exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
exitIfUncommittedChanges({
|
exitIfUncommittedChanges({
|
||||||
projectDirPath: buildContext.projectDirPath
|
projectDirPath: buildContext.projectDirPath
|
||||||
});
|
});
|
||||||
@ -51,17 +35,35 @@ export async function command(params: { buildContext: BuildContext }) {
|
|||||||
|
|
||||||
switch (accountThemeType) {
|
switch (accountThemeType) {
|
||||||
case "Multi-Page":
|
case "Multi-Page":
|
||||||
fs.cpSync(
|
{
|
||||||
pathJoin(
|
if (
|
||||||
getThisCodebaseRootDirPath(),
|
fs.existsSync(accountThemeSrcDirPath) &&
|
||||||
"src",
|
fs.readdirSync(accountThemeSrcDirPath).length > 0
|
||||||
"bin",
|
) {
|
||||||
"initialize-account-theme",
|
console.warn(
|
||||||
"multi-page-boilerplate"
|
chalk.red(
|
||||||
),
|
`There is already a ${pathRelative(
|
||||||
accountThemeSrcDirPath,
|
process.cwd(),
|
||||||
{ recursive: true }
|
accountThemeSrcDirPath
|
||||||
);
|
)} directory in your project. Aborting.`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
process.exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.cpSync(
|
||||||
|
pathJoin(
|
||||||
|
getThisCodebaseRootDirPath(),
|
||||||
|
"src",
|
||||||
|
"bin",
|
||||||
|
"initialize-account-theme",
|
||||||
|
"multi-page-boilerplate"
|
||||||
|
),
|
||||||
|
accountThemeSrcDirPath,
|
||||||
|
{ recursive: true }
|
||||||
|
);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "Single-Page":
|
case "Single-Page":
|
||||||
{
|
{
|
||||||
|
@ -1,17 +1,24 @@
|
|||||||
import { join as pathJoin, relative as pathRelative } from "path";
|
|
||||||
import { transformCodebase } from "./tools/transformCodebase";
|
|
||||||
import type { BuildContext } from "./shared/buildContext";
|
import type { BuildContext } from "./shared/buildContext";
|
||||||
import * as fs from "fs";
|
import cliSelect from "cli-select";
|
||||||
import { downloadAndExtractArchive } from "./tools/downloadAndExtractArchive";
|
|
||||||
import { maybeDelegateCommandToCustomHandler } from "./shared/customHandler_delegate";
|
import { maybeDelegateCommandToCustomHandler } from "./shared/customHandler_delegate";
|
||||||
import { assert } from "tsafe/assert";
|
import { exitIfUncommittedChanges } from "./shared/exitIfUncommittedChanges";
|
||||||
import { getSupportedDockerImageTags } from "./start-keycloak/getSupportedDockerImageTags";
|
|
||||||
|
import { dirname as pathDirname, join as pathJoin, relative as pathRelative } from "path";
|
||||||
|
import * as fs from "fs";
|
||||||
|
import { assert, is, type Equals } from "tsafe/assert";
|
||||||
|
import { id } from "tsafe/id";
|
||||||
|
import { addSyncExtensionsToPostinstallScript } from "./shared/addSyncExtensionsToPostinstallScript";
|
||||||
|
import { getIsPrettierAvailable, runPrettier } from "./tools/runPrettier";
|
||||||
|
import { npmInstall } from "./tools/npmInstall";
|
||||||
|
import * as child_process from "child_process";
|
||||||
|
import { z } from "zod";
|
||||||
|
import chalk from "chalk";
|
||||||
|
|
||||||
export async function command(params: { buildContext: BuildContext }) {
|
export async function command(params: { buildContext: BuildContext }) {
|
||||||
const { buildContext } = params;
|
const { buildContext } = params;
|
||||||
|
|
||||||
const { hasBeenHandled } = maybeDelegateCommandToCustomHandler({
|
const { hasBeenHandled } = maybeDelegateCommandToCustomHandler({
|
||||||
commandName: "initialize-email-theme",
|
commandName: "initialize-account-theme",
|
||||||
buildContext
|
buildContext
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -19,6 +26,10 @@ export async function command(params: { buildContext: BuildContext }) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exitIfUncommittedChanges({
|
||||||
|
projectDirPath: buildContext.projectDirPath
|
||||||
|
});
|
||||||
|
|
||||||
const emailThemeSrcDirPath = pathJoin(buildContext.themeSrcDirPath, "email");
|
const emailThemeSrcDirPath = pathJoin(buildContext.themeSrcDirPath, "email");
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -26,71 +37,110 @@ export async function command(params: { buildContext: BuildContext }) {
|
|||||||
fs.readdirSync(emailThemeSrcDirPath).length > 0
|
fs.readdirSync(emailThemeSrcDirPath).length > 0
|
||||||
) {
|
) {
|
||||||
console.warn(
|
console.warn(
|
||||||
`There is already a non empty ${pathRelative(
|
chalk.red(
|
||||||
process.cwd(),
|
`There is already a ${pathRelative(
|
||||||
emailThemeSrcDirPath
|
process.cwd(),
|
||||||
)} directory in your project. Aborting.`
|
emailThemeSrcDirPath
|
||||||
|
)} directory in your project. Aborting.`
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
process.exit(-1);
|
process.exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Initialize with the base email theme from which version of Keycloak?");
|
const { value: emailThemeType } = await cliSelect({
|
||||||
|
values: ["native (FreeMarker)" as const, "jsx-email (React)" as const]
|
||||||
|
}).catch(() => {
|
||||||
|
process.exit(-1);
|
||||||
|
});
|
||||||
|
|
||||||
const { extractedDirPath } = await downloadAndExtractArchive({
|
if (emailThemeType === "jsx-email (React)") {
|
||||||
url: await (async () => {
|
console.log(
|
||||||
const { latestMajorTags } = await getSupportedDockerImageTags({
|
[
|
||||||
buildContext
|
"There is currently no automated support for keycloakify-email, it has to be done manually, see documentation:",
|
||||||
|
"https://docs.keycloakify.dev/theme-types/email-theme"
|
||||||
|
].join("\n")
|
||||||
|
);
|
||||||
|
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsedPackageJson = (() => {
|
||||||
|
type ParsedPackageJson = {
|
||||||
|
scripts?: Record<string, string | undefined>;
|
||||||
|
dependencies?: Record<string, string | undefined>;
|
||||||
|
devDependencies?: Record<string, string | undefined>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const zParsedPackageJson = (() => {
|
||||||
|
type TargetType = ParsedPackageJson;
|
||||||
|
|
||||||
|
const zTargetType = z.object({
|
||||||
|
scripts: z.record(z.union([z.string(), z.undefined()])).optional(),
|
||||||
|
dependencies: z.record(z.union([z.string(), z.undefined()])).optional(),
|
||||||
|
devDependencies: z.record(z.union([z.string(), z.undefined()])).optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
const keycloakVersion = latestMajorTags[0];
|
assert<Equals<z.infer<typeof zTargetType>, TargetType>>;
|
||||||
|
|
||||||
assert(keycloakVersion !== undefined);
|
return id<z.ZodType<TargetType>>(zTargetType);
|
||||||
|
})();
|
||||||
|
const parsedPackageJson = JSON.parse(
|
||||||
|
fs.readFileSync(buildContext.packageJsonFilePath).toString("utf8")
|
||||||
|
);
|
||||||
|
|
||||||
return `https://repo1.maven.org/maven2/org/keycloak/keycloak-themes/${keycloakVersion}/keycloak-themes-${keycloakVersion}.jar`;
|
zParsedPackageJson.parse(parsedPackageJson);
|
||||||
})(),
|
|
||||||
cacheDirPath: buildContext.cacheDirPath,
|
|
||||||
fetchOptions: buildContext.fetchOptions,
|
|
||||||
uniqueIdOfOnArchiveFile: "extractOnlyEmailTheme",
|
|
||||||
onArchiveFile: async ({ fileRelativePath, writeFile }) => {
|
|
||||||
const fileRelativePath_target = pathRelative(
|
|
||||||
pathJoin("theme", "base", "email"),
|
|
||||||
fileRelativePath
|
|
||||||
);
|
|
||||||
|
|
||||||
if (fileRelativePath_target.startsWith("..")) {
|
assert(is<ParsedPackageJson>(parsedPackageJson));
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await writeFile({ fileRelativePath: fileRelativePath_target });
|
return parsedPackageJson;
|
||||||
}
|
})();
|
||||||
|
|
||||||
|
addSyncExtensionsToPostinstallScript({
|
||||||
|
parsedPackageJson,
|
||||||
|
buildContext
|
||||||
});
|
});
|
||||||
|
|
||||||
transformCodebase({
|
const moduleName = `@keycloakify/email-native`;
|
||||||
srcDirPath: extractedDirPath,
|
|
||||||
destDirPath: emailThemeSrcDirPath
|
const [version] = (
|
||||||
});
|
JSON.parse(
|
||||||
|
child_process
|
||||||
|
.execSync(`npm show ${moduleName} versions --json`)
|
||||||
|
.toString("utf8")
|
||||||
|
.trim()
|
||||||
|
) as string[]
|
||||||
|
)
|
||||||
|
.reverse()
|
||||||
|
.filter(version => !version.includes("-"));
|
||||||
|
|
||||||
|
assert(version !== undefined);
|
||||||
|
|
||||||
|
(parsedPackageJson.dependencies ??= {})[moduleName] = `~${version}`;
|
||||||
|
|
||||||
|
if (parsedPackageJson.devDependencies !== undefined) {
|
||||||
|
delete parsedPackageJson.devDependencies[moduleName];
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const themePropertyFilePath = pathJoin(emailThemeSrcDirPath, "theme.properties");
|
let sourceCode = JSON.stringify(parsedPackageJson, undefined, 2);
|
||||||
|
|
||||||
|
if (await getIsPrettierAvailable()) {
|
||||||
|
sourceCode = await runPrettier({
|
||||||
|
sourceCode,
|
||||||
|
filePath: buildContext.packageJsonFilePath
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
themePropertyFilePath,
|
buildContext.packageJsonFilePath,
|
||||||
Buffer.from(
|
Buffer.from(sourceCode, "utf8")
|
||||||
[
|
|
||||||
`parent=base`,
|
|
||||||
fs.readFileSync(themePropertyFilePath).toString("utf8")
|
|
||||||
].join("\n"),
|
|
||||||
"utf8"
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(
|
await npmInstall({
|
||||||
`The \`${pathJoin(
|
packageJsonDirPath: pathDirname(buildContext.packageJsonFilePath)
|
||||||
".",
|
});
|
||||||
pathRelative(process.cwd(), emailThemeSrcDirPath)
|
|
||||||
)}\` directory have been created.`
|
console.log(chalk.green("Email theme initialized."));
|
||||||
);
|
|
||||||
console.log("You can delete any file you don't modify.");
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { dirname as pathDirname, relative as pathRelative, sep as pathSep } from "path";
|
import { dirname as pathDirname, relative as pathRelative, sep as pathSep } from "path";
|
||||||
import { assert } from "tsafe/assert";
|
import { assert } from "tsafe/assert";
|
||||||
import type { BuildContext } from "../buildContext";
|
import type { BuildContext } from "./buildContext";
|
||||||
|
|
||||||
export type BuildContextLike = {
|
export type BuildContextLike = {
|
||||||
projectDirPath: string;
|
projectDirPath: string;
|
@ -1,5 +1,5 @@
|
|||||||
import { dirname as pathDirname, join as pathJoin, relative as pathRelative } from "path";
|
import { dirname as pathDirname, join as pathJoin, relative as pathRelative } from "path";
|
||||||
import type { BuildContext } from "../buildContext";
|
import type { BuildContext } from "./buildContext";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { assert, is, type Equals } from "tsafe/assert";
|
import { assert, is, type Equals } from "tsafe/assert";
|
||||||
import { id } from "tsafe/id";
|
import { id } from "tsafe/id";
|
||||||
@ -7,8 +7,8 @@ import {
|
|||||||
addSyncExtensionsToPostinstallScript,
|
addSyncExtensionsToPostinstallScript,
|
||||||
type BuildContextLike as BuildContextLike_addSyncExtensionsToPostinstallScript
|
type BuildContextLike as BuildContextLike_addSyncExtensionsToPostinstallScript
|
||||||
} from "./addSyncExtensionsToPostinstallScript";
|
} from "./addSyncExtensionsToPostinstallScript";
|
||||||
import { getIsPrettierAvailable, runPrettier } from "../../tools/runPrettier";
|
import { getIsPrettierAvailable, runPrettier } from "../tools/runPrettier";
|
||||||
import { npmInstall } from "../../tools/npmInstall";
|
import { npmInstall } from "../tools/npmInstall";
|
||||||
import * as child_process from "child_process";
|
import * as child_process from "child_process";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
@ -1 +0,0 @@
|
|||||||
export * from "./initializeSpa";
|
|
@ -99,6 +99,12 @@ function addCommentToSourceCode(params: {
|
|||||||
return toResult(commentLines.map(line => `# ${line}`).join("\n"));
|
return toResult(commentLines.map(line => `# ${line}`).join("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fileRelativePath.endsWith(".ftl")) {
|
||||||
|
return toResult(
|
||||||
|
[`<#--`, ...commentLines.map(line => ` ${line}`), `-->`].join("\n")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (fileRelativePath.endsWith(".html") || fileRelativePath.endsWith(".svg")) {
|
if (fileRelativePath.endsWith(".html") || fileRelativePath.endsWith(".svg")) {
|
||||||
const comment = [
|
const comment = [
|
||||||
`<!--`,
|
`<!--`,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user