import * as crypto from 'crypto'; import * as fs from 'fs'; import { join as pathJoin } from 'path'; import type { BuildContext } from './core'; import { getIsPrettierAvailable, runPrettier } from './tools/runPrettier'; export async function command(params: { buildContext: BuildContext }) { const { buildContext } = params; const filePath = pathJoin(buildContext.themeSrcDirPath, 'kc.gen.ts'); const svelteFilePath = pathJoin(buildContext.themeSrcDirPath, 'kc.gen.svelte'); const hasLoginTheme = buildContext.implementedThemeTypes.login.isImplemented; const hasAccountTheme = buildContext.implementedThemeTypes.account.isImplemented; const hasAdminTheme = buildContext.implementedThemeTypes.admin.isImplemented; const newContent = [ `/* eslint-disable */`, ``, `// @ts-nocheck`, ``, `// noinspection JSUnusedGlobalSymbols`, ``, `export type ThemeName = ${buildContext.themeNames.map((themeName) => `"${themeName}"`).join(' | ')};`, ``, `export const themeNames: ThemeName[] = [${buildContext.themeNames.map((themeName) => `"${themeName}"`).join(', ')}];`, ``, `export type KcEnvName = ${buildContext.environmentVariables.length === 0 ? 'never' : buildContext.environmentVariables.map(({ name }) => `"${name}"`).join(' | ')};`, ``, `export const kcEnvNames: KcEnvName[] = [${buildContext.environmentVariables.map(({ name }) => `"${name}"`).join(', ')}];`, ``, `export const kcEnvDefaults: Record = ${JSON.stringify( Object.fromEntries( buildContext.environmentVariables.map(({ name, default: defaultValue }) => [name, defaultValue]), ), null, 2, )};`, ``, `export type KcContext =`, hasLoginTheme && ` | import("./login/KcContext").KcContext`, hasAccountTheme && ` | import("./account/KcContext").KcContext`, hasAdminTheme && ` | import("./admin/KcContext").KcContext`, ``, `declare global {`, ` interface Window {`, ` kcContext?: KcContext;`, ` }`, `}`, ``, ] .filter((item) => typeof item === 'string') .join('\n'); const newSvelteContent = [ ` import type { Component } from 'svelte';`, ` import type { KcContext } from './kc.gen';`, ``, ` const { kcContext, Fallback }: { kcContext: KcContext; Fallback?: Component } = $props();`, ``, hasLoginTheme && ` const KcLoginPage = import("./login/KcPage.svelte");`, hasAccountTheme && ` const KcAccountPage = import("./account/KcPage.svelte");`, hasAdminTheme && ` const KcAdminPage = import("./admin/KcPage.svelte");`, ``, ``, `{#if kcContext.themeType === 'login'}`, hasLoginTheme && ` {#await KcLoginPage}`, hasLoginTheme && ` {#if Fallback}`, hasLoginTheme && ` `, hasLoginTheme && ` {/if}`, hasLoginTheme && ` {:then { default: KcPage }}`, hasLoginTheme && ` `, hasLoginTheme && ` {/await}`, !hasLoginTheme && ` `, `{:else if kcContext.themeType === 'account'}`, hasAccountTheme && ` {#await KcAccountPage}`, hasAccountTheme && ` {#if Fallback}`, hasAccountTheme && ` `, hasAccountTheme && ` {/if}`, hasAccountTheme && ` {:then { default: KcPage }}`, hasAccountTheme && ` `, hasAccountTheme && ` {/await}`, !hasAccountTheme && ` `, // TODO: admin theme `{/if}`, ] .filter((item) => typeof item === 'string') .join('\n'); const hash = crypto.createHash('sha256').update(newContent).digest('hex'); const svelteHash = crypto.createHash('sha256').update(newSvelteContent).digest('hex'); skip_if_no_changes: { if (!fs.existsSync(filePath)) { break skip_if_no_changes; } const currentContent = fs.readFileSync(filePath).toString('utf8'); if (!currentContent.includes(hash)) { break skip_if_no_changes; } return; } skip_if_no_svelte_changes: { if (!fs.existsSync(svelteFilePath)) { break skip_if_no_svelte_changes; } const currentContent = fs.readFileSync(svelteFilePath).toString('utf8'); if (!currentContent.includes(svelteHash)) { break skip_if_no_svelte_changes; } return; } let sourceCode = [ `// This file is auto-generated by keycloakify. Do not edit it manually.`, `// Hash: ${hash}`, ``, newContent, ].join('\n'); let svelteSourceCode = [ `