keycloak_theme/src/bin/add-story.ts

138 lines
4.1 KiB
TypeScript
Raw Normal View History

2024-06-06 07:41:01 +02:00
import { getThisCodebaseRootDirPath } from "./tools/getThisCodebaseRootDirPath";
import cliSelect from "cli-select";
import {
2024-07-13 19:33:59 +02:00
LOGIN_THEME_PAGE_IDS,
ACCOUNT_THEME_PAGE_IDS,
2024-06-06 07:41:01 +02:00
type LoginThemePageId,
type AccountThemePageId,
2024-07-13 19:33:59 +02:00
THEME_TYPES,
2024-06-06 07:41:01 +02:00
type ThemeType
} from "./shared/constants";
import { capitalize } from "tsafe/capitalize";
import * as fs from "fs";
import { join as pathJoin, relative as pathRelative, dirname as pathDirname } from "path";
import { kebabCaseToCamelCase } from "./tools/kebabCaseToSnakeCase";
import { assert, Equals } from "tsafe/assert";
import type { CliCommandOptions } from "./main";
2024-06-09 09:15:16 +02:00
import { getBuildContext } from "./shared/buildContext";
2024-06-06 07:41:01 +02:00
import chalk from "chalk";
export async function command(params: { cliCommandOptions: CliCommandOptions }) {
const { cliCommandOptions } = params;
2024-06-09 09:15:16 +02:00
const buildContext = getBuildContext({
2024-06-06 07:41:01 +02:00
cliCommandOptions
});
console.log(chalk.cyan("Theme type:"));
const themeType = await (async () => {
const values = THEME_TYPES.filter(themeType => {
switch (themeType) {
case "account":
return buildContext.implementedThemeTypes.account.isImplemented;
case "login":
return buildContext.implementedThemeTypes.login.isImplemented;
}
assert<Equals<typeof themeType, never>>(false);
});
assert(values.length > 0, "No theme is implemented in this project");
if (values.length === 1) {
return values[0];
}
const { value } = await cliSelect<ThemeType>({
values
}).catch(() => {
process.exit(-1);
});
return value;
})();
2024-06-06 07:41:01 +02:00
if (
themeType === "account" &&
(assert(buildContext.implementedThemeTypes.account.isImplemented),
buildContext.implementedThemeTypes.account.type === "Single-Page")
) {
console.log(
`${chalk.red("✗")} Sorry, there is no Storybook support for Single-Page Account themes.`
);
process.exit(0);
}
2024-06-06 07:41:01 +02:00
console.log(`${themeType}`);
console.log(chalk.cyan("Select the page you want to create a Storybook for:"));
const { value: pageId } = await cliSelect<LoginThemePageId | AccountThemePageId>({
values: (() => {
switch (themeType) {
case "login":
2024-07-13 19:33:59 +02:00
return [...LOGIN_THEME_PAGE_IDS];
2024-06-06 07:41:01 +02:00
case "account":
2024-07-13 19:33:59 +02:00
return [...ACCOUNT_THEME_PAGE_IDS];
2024-06-06 07:41:01 +02:00
}
assert<Equals<typeof themeType, never>>(false);
})()
}).catch(() => {
process.exit(-1);
});
console.log(`${pageId}`);
const componentBasename = capitalize(kebabCaseToCamelCase(pageId)).replace(
/ftl$/,
"stories.tsx"
);
const targetFilePath = pathJoin(
buildContext.themeSrcDirPath,
2024-06-06 07:41:01 +02:00
themeType,
"pages",
componentBasename
);
if (fs.existsSync(targetFilePath)) {
console.log(`${pathRelative(process.cwd(), targetFilePath)} already exists`);
process.exit(-1);
}
const componentCode = fs
.readFileSync(
pathJoin(
getThisCodebaseRootDirPath(),
"stories",
themeType,
"pages",
componentBasename
)
)
2024-06-06 09:13:40 +02:00
.toString("utf8")
2024-06-28 06:46:26 +02:00
.replace('import React from "react";\n', "")
.replace(/from "[./]+dist\//, 'from "keycloakify/');
2024-06-06 09:13:40 +02:00
{
const targetDirPath = pathDirname(targetFilePath);
if (!fs.existsSync(targetDirPath)) {
fs.mkdirSync(targetDirPath, { recursive: true });
}
}
2024-06-06 07:41:01 +02:00
fs.writeFileSync(targetFilePath, Buffer.from(componentCode, "utf8"));
console.log(
2024-06-06 09:13:40 +02:00
[
`${chalk.green("✓")} ${chalk.bold(
pathJoin(".", pathRelative(process.cwd(), targetFilePath))
)} copy pasted from the Keycloakify source code into your project`,
`You can start storybook with ${chalk.bold("npm run storybook")}`
2024-06-06 09:13:40 +02:00
].join("\n")
2024-06-06 07:41:01 +02:00
);
}