import { join as pathJoin, relative as pathRelative, dirname as pathDirname } from "path"; import type { BuildContext } from "../shared/buildContext"; import * as fs from "fs"; import chalk from "chalk"; import { getLatestsSemVersionedTag, type BuildContextLike as BuildContextLike_getLatestsSemVersionedTag } from "../shared/getLatestsSemVersionedTag"; import { SemVer } from "../tools/SemVer"; import fetch from "make-fetch-happen"; import { z } from "zod"; import { assert, type Equals } from "tsafe/assert"; import { is } from "tsafe/is"; import { id } from "tsafe/id"; import { npmInstall } from "../tools/npmInstall"; import { copyBoilerplate } from "./copyBoilerplate"; import { getThisCodebaseRootDirPath } from "../tools/getThisCodebaseRootDirPath"; type BuildContextLike = BuildContextLike_getLatestsSemVersionedTag & { fetchOptions: BuildContext["fetchOptions"]; packageJsonFilePath: string; }; assert(); export async function initializeAccountTheme_singlePage(params: { accountThemeSrcDirPath: string; buildContext: BuildContextLike; }) { const { accountThemeSrcDirPath, buildContext } = params; const OWNER = "keycloakify"; const REPO = "keycloak-account-ui"; const [semVersionedTag] = await getLatestsSemVersionedTag({ owner: OWNER, repo: REPO, count: 1, doIgnoreReleaseCandidates: false, buildContext }); const dependencies = await fetch( `https://raw.githubusercontent.com/${OWNER}/${REPO}/${semVersionedTag.tag}/dependencies.gen.json`, buildContext.fetchOptions ) .then(r => r.json()) .then( (() => { type Dependencies = { dependencies: Record; devDependencies?: Record; }; const zDependencies = (() => { type TargetType = Dependencies; const zTargetType = z.object({ dependencies: z.record(z.string()), devDependencies: z.record(z.string()).optional() }); assert, TargetType>>(); return id>(zTargetType); })(); return o => zDependencies.parse(o); })() ); dependencies.dependencies["@keycloakify/keycloak-account-ui"] = SemVer.stringify( semVersionedTag.version ); const parsedPackageJson = (() => { type ParsedPackageJson = { dependencies?: Record; devDependencies?: Record; }; const zParsedPackageJson = (() => { type TargetType = ParsedPackageJson; const zTargetType = z.object({ dependencies: z.record(z.string()).optional(), devDependencies: z.record(z.string()).optional() }); assert, TargetType>>(); return id>(zTargetType); })(); const parsedPackageJson = JSON.parse( fs.readFileSync(buildContext.packageJsonFilePath).toString("utf8") ); zParsedPackageJson.parse(parsedPackageJson); assert(is(parsedPackageJson)); return parsedPackageJson; })(); parsedPackageJson.dependencies = { ...parsedPackageJson.dependencies, ...dependencies.dependencies }; parsedPackageJson.devDependencies = { ...parsedPackageJson.devDependencies, ...dependencies.devDependencies }; if (Object.keys(parsedPackageJson.devDependencies).length === 0) { delete parsedPackageJson.devDependencies; } fs.writeFileSync( buildContext.packageJsonFilePath, JSON.stringify(parsedPackageJson, undefined, 4) ); run_npm_install: { if ( JSON.parse( fs .readFileSync(pathJoin(getThisCodebaseRootDirPath(), "package.json")) .toString("utf8") )["version"] === "0.0.0" ) { //NOTE: Linked version break run_npm_install; } npmInstall({ packageJsonDirPath: pathDirname(buildContext.packageJsonFilePath) }); } copyBoilerplate({ accountThemeType: "Single-Page", accountThemeSrcDirPath }); console.log( [ chalk.green( "The Single-Page account theme has been successfully initialized." ), `Using Account UI of Keycloak version: ${chalk.bold(semVersionedTag.tag.split("-")[0])}`, `Directory created: ${chalk.bold(pathRelative(process.cwd(), accountThemeSrcDirPath))}`, `Dependencies added to your project's package.json: `, chalk.bold(JSON.stringify(dependencies, null, 2)) ].join("\n") ); }