keycloakify 11.8.45 → 11.8.47-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/254.index.js +283 -0
- package/bin/30.index.js +25 -0
- package/bin/{864.index.js → 309.index.js} +6944 -28439
- package/bin/311.index.js +198 -0
- package/bin/{313.index.js → 355.index.js} +101 -147
- package/bin/{84.index.js → 502.index.js} +147 -101
- package/bin/626.index.js +194 -0
- package/bin/{698.index.js → 656.index.js} +101 -147
- package/bin/675.index.js +177 -0
- package/bin/69.index.js +1 -1
- package/bin/762.index.js +1475 -0
- package/bin/780.index.js +4 -2
- package/bin/786.index.js +115 -0
- package/bin/895.index.js +21501 -0
- package/bin/{618.index.js → 932.index.js} +117 -163
- package/bin/949.index.js +1 -1
- package/bin/97.index.js +537 -4
- package/bin/init/index.d.ts +1 -0
- package/bin/init/init.d.ts +3 -0
- package/bin/init/setupEslint.d.ts +4 -0
- package/bin/init/setupVitePluginIfNeeded.d.ts +4 -0
- package/bin/initialize-login-theme.d.ts +4 -0
- package/bin/main.js +19 -30
- package/bin/shared/customHandler.d.ts +1 -1
- package/bin/shared/customHandler.js.map +1 -1
- package/package.json +82 -66
- package/src/bin/init/index.ts +1 -0
- package/src/bin/init/init.ts +354 -0
- package/src/bin/init/setupEslint.ts +80 -0
- package/src/bin/init/setupVitePluginIfNeeded.ts +143 -0
- package/src/bin/initialize-account-theme/initialize-account-theme.ts +4 -0
- package/src/bin/initialize-login-theme.ts +323 -0
- package/src/bin/main.ts +14 -0
- package/src/bin/shared/buildContext.ts +2 -37
- package/src/bin/shared/customHandler.ts +3 -1
- package/src/bin/sync-extensions/extensionModuleMeta.ts +89 -73
- package/src/bin/sync-extensions/managedGitignoreFiles.ts +32 -2
- package/vite-plugin/index.js +1 -24
- package/bin/433.index.js +0 -140
- /package/res/public/keycloakify-dev-resources/account/{account/css → css}/account.css +0 -0
- /package/res/public/keycloakify-dev-resources/account/{account/img → img}/icon-sidebar-active.png +0 -0
- /package/res/public/keycloakify-dev-resources/account/{account/img → img}/keycloak-logo.png +0 -0
- /package/res/public/keycloakify-dev-resources/account/{account/img → img}/logo.png +0 -0
- /package/res/public/keycloakify-dev-resources/account/{account/resources-common → resources-common}/img/favicon.ico +0 -0
- /package/res/public/keycloakify-dev-resources/account/{account/resources-common → resources-common}/node_modules/patternfly/dist/css/patternfly-additions.min.css +0 -0
- /package/res/public/keycloakify-dev-resources/account/{account/resources-common → resources-common}/node_modules/patternfly/dist/css/patternfly.min.css +0 -0
- /package/res/public/keycloakify-dev-resources/account/{account/resources-common → resources-common}/node_modules/patternfly/dist/fonts/OpenSans-Bold-webfont.woff2 +0 -0
- /package/res/public/keycloakify-dev-resources/account/{account/resources-common → resources-common}/node_modules/patternfly/dist/fonts/OpenSans-Light-webfont.woff2 +0 -0
- /package/res/public/keycloakify-dev-resources/account/{account/resources-common → resources-common}/node_modules/patternfly/dist/fonts/OpenSans-Regular-webfont.woff2 +0 -0
- /package/res/public/keycloakify-dev-resources/account/{account/resources-common → resources-common}/node_modules/patternfly/dist/fonts/OpenSans-Semibold-webfont.woff2 +0 -0
- /package/res/public/keycloakify-dev-resources/account/{account/resources-common → resources-common}/node_modules/patternfly/dist/fonts/PatternFlyIcons-webfont.ttf +0 -0
- /package/res/public/keycloakify-dev-resources/account/{account/resources-common → resources-common}/node_modules/patternfly/dist/fonts/PatternFlyIcons-webfont.woff +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/css → css}/login.css +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/img → img}/feedback-error-arrow-down.png +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/img → img}/feedback-error-sign.png +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/img → img}/feedback-success-arrow-down.png +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/img → img}/feedback-success-sign.png +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/img → img}/feedback-warning-arrow-down.png +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/img → img}/feedback-warning-sign.png +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/img → img}/keycloak-bg.png +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/img → img}/keycloak-logo-text.png +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/img → img}/keycloak-logo.png +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/js → js}/authChecker.js +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/js → js}/common.js +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/js → js}/kcMultivalued.js +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/js → js}/kcNumberFormat.js +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/js → js}/kcNumberUnFormat.js +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/js → js}/menu-button-links.js +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/js → js}/passkeysConditionalAuth.js +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/js → js}/passwordVisibility.js +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/js → js}/userProfile.js +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/js → js}/webauthnAuthenticate.js +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/js → js}/webauthnRegister.js +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/img/favicon.ico +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/lib/pficon/pficon.css +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/lib/pficon/pficon.woff2 +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/@patternfly/patternfly/assets/fonts/RedHatDisplay/RedHatDisplay-Bold.woff +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/@patternfly/patternfly/assets/fonts/RedHatDisplay/RedHatDisplay-Bold.woff2 +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/@patternfly/patternfly/assets/fonts/overpass-webfont/overpass-bold.woff +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/@patternfly/patternfly/assets/fonts/overpass-webfont/overpass-bold.woff2 +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/@patternfly/patternfly/patternfly.min.css +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/jquery/dist/jquery.min.js +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/patternfly/dist/css/patternfly-additions.min.css +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/patternfly/dist/css/patternfly.min.css +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/patternfly/dist/fonts/OpenSans-Bold-webfont.ttf +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/patternfly/dist/fonts/OpenSans-Bold-webfont.woff +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/patternfly/dist/fonts/OpenSans-Bold-webfont.woff2 +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/patternfly/dist/fonts/OpenSans-Light-webfont.woff2 +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/patternfly/dist/fonts/OpenSans-Regular-webfont.woff2 +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/patternfly/dist/fonts/OpenSans-Semibold-webfont.woff2 +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/patternfly/dist/fonts/OpenSans-SemiboldItalic-webfont.ttf +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/patternfly/dist/fonts/OpenSans-SemiboldItalic-webfont.woff +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/patternfly/dist/fonts/OpenSans-SemiboldItalic-webfont.woff2 +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/patternfly/dist/fonts/PatternFlyIcons-webfont.ttf +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/patternfly/dist/fonts/PatternFlyIcons-webfont.woff +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/patternfly/dist/fonts/fontawesome-webfont.woff2 +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/patternfly/dist/img/bg-login.jpg +0 -0
- /package/res/public/keycloakify-dev-resources/login/{login/resources-common → resources-common}/node_modules/rfc4648/lib/rfc4648.js +0 -0
@@ -0,0 +1,354 @@
|
|
1
|
+
import { setupVitePluginIfNeeded } from "./setupVitePluginIfNeeded";
|
2
|
+
import { setupEslint } from "./setupEslint";
|
3
|
+
import { getBuildContext } from "../shared/buildContext";
|
4
|
+
import { maybeDelegateCommandToCustomHandler } from "../shared/customHandler_delegate";
|
5
|
+
import { z } from "zod";
|
6
|
+
import { assert, type Equals, is } from "tsafe/assert";
|
7
|
+
import { id } from "tsafe/id";
|
8
|
+
import * as fs from "fs/promises";
|
9
|
+
import { runPrettier, getIsPrettierAvailable } from "../tools/runPrettier";
|
10
|
+
import cliSelect from "cli-select";
|
11
|
+
import { THEME_TYPES } from "../shared/constants";
|
12
|
+
import chalk from "chalk";
|
13
|
+
import { join as pathJoin, relative as pathRelative } from "path";
|
14
|
+
import { existsAsync } from "../tools/fs.existsAsync";
|
15
|
+
import { KEYCLOAK_THEME } from "../shared/constants";
|
16
|
+
|
17
|
+
export async function command(params: { projectDirPath: string }) {
|
18
|
+
const { projectDirPath } = params;
|
19
|
+
|
20
|
+
await setupVitePluginIfNeeded({ projectDirPath });
|
21
|
+
|
22
|
+
const buildContext = getBuildContext({ projectDirPath });
|
23
|
+
|
24
|
+
const { hasBeenHandled } = await maybeDelegateCommandToCustomHandler({
|
25
|
+
commandName: "init",
|
26
|
+
buildContext
|
27
|
+
});
|
28
|
+
|
29
|
+
if (hasBeenHandled) {
|
30
|
+
return;
|
31
|
+
}
|
32
|
+
|
33
|
+
await setupEslint({ projectDirPath });
|
34
|
+
|
35
|
+
let doAddRunDevScript = false;
|
36
|
+
|
37
|
+
setup_src: {
|
38
|
+
if (buildContext.bundler !== "vite") {
|
39
|
+
break setup_src;
|
40
|
+
}
|
41
|
+
|
42
|
+
const srcDirPath = pathJoin(buildContext.projectDirPath, "src");
|
43
|
+
|
44
|
+
const mainTsxFilePath = pathJoin(srcDirPath, "main.tsx");
|
45
|
+
|
46
|
+
if (!(await existsAsync(mainTsxFilePath))) {
|
47
|
+
break setup_src;
|
48
|
+
}
|
49
|
+
|
50
|
+
const isAlreadySetup = await (async () => {
|
51
|
+
if (buildContext.themeSrcDirPath !== srcDirPath) {
|
52
|
+
return true;
|
53
|
+
}
|
54
|
+
|
55
|
+
{
|
56
|
+
const basenames = await fs.readdir(srcDirPath);
|
57
|
+
|
58
|
+
for (const basename of basenames) {
|
59
|
+
const path = pathJoin(srcDirPath, basename);
|
60
|
+
|
61
|
+
if (!(await fs.stat(path)).isFile()) {
|
62
|
+
continue;
|
63
|
+
}
|
64
|
+
|
65
|
+
if ((await fs.readFile(path)).toString("utf8").includes("./kc.gen")) {
|
66
|
+
return true;
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
for (const themeType of [...THEME_TYPES, "email"]) {
|
72
|
+
if (!(await existsAsync(pathJoin(srcDirPath, themeType)))) {
|
73
|
+
continue;
|
74
|
+
}
|
75
|
+
return true;
|
76
|
+
}
|
77
|
+
|
78
|
+
return false;
|
79
|
+
})();
|
80
|
+
|
81
|
+
if (isAlreadySetup) {
|
82
|
+
break setup_src;
|
83
|
+
}
|
84
|
+
|
85
|
+
const doSetupAsStandalone = await (async () => {
|
86
|
+
const relativeProjectDirPath = pathRelative(
|
87
|
+
process.cwd(),
|
88
|
+
buildContext.projectDirPath
|
89
|
+
);
|
90
|
+
|
91
|
+
console.log(
|
92
|
+
chalk.cyan(
|
93
|
+
[
|
94
|
+
relativeProjectDirPath === ""
|
95
|
+
? "This Vite project"
|
96
|
+
: `The Vite project at ${relativeProjectDirPath}`,
|
97
|
+
"is it dedicated *only* to building a Keycloak theme?"
|
98
|
+
].join(" ")
|
99
|
+
)
|
100
|
+
);
|
101
|
+
|
102
|
+
const YES = "Yes — this project is only for the Keycloak theme (recommended)";
|
103
|
+
const NO =
|
104
|
+
"No — I'm building an app and a Keycloak theme in the same project (advanced)";
|
105
|
+
|
106
|
+
const { value } = await cliSelect({ values: [YES, NO] }).catch(() => {
|
107
|
+
process.exit(-1);
|
108
|
+
});
|
109
|
+
|
110
|
+
console.log(`${value}\n`);
|
111
|
+
|
112
|
+
return value === YES;
|
113
|
+
})();
|
114
|
+
|
115
|
+
let files: { relativeFilePath: string; fileContent: string }[];
|
116
|
+
|
117
|
+
if (doSetupAsStandalone) {
|
118
|
+
const viteEnvDTsFilePath = pathJoin(
|
119
|
+
buildContext.themeSrcDirPath,
|
120
|
+
"vite-env.d.ts"
|
121
|
+
);
|
122
|
+
|
123
|
+
const viteEnvDTsContent = await fs.readFile(viteEnvDTsFilePath);
|
124
|
+
|
125
|
+
await fs.rm(srcDirPath, { recursive: true });
|
126
|
+
|
127
|
+
await fs.mkdir(srcDirPath);
|
128
|
+
|
129
|
+
await fs.writeFile(viteEnvDTsFilePath, viteEnvDTsContent);
|
130
|
+
|
131
|
+
files = [
|
132
|
+
{
|
133
|
+
relativeFilePath: "main.tsx",
|
134
|
+
fileContent: [
|
135
|
+
`if (window.kcContext !== undefined) {`,
|
136
|
+
` import("./main-kc");`,
|
137
|
+
`} else {`,
|
138
|
+
` import("./main-kc.dev");`,
|
139
|
+
`}`
|
140
|
+
].join("\n")
|
141
|
+
},
|
142
|
+
{
|
143
|
+
relativeFilePath: "main-kc.dev.tsx",
|
144
|
+
fileContent: `export {};\n`
|
145
|
+
},
|
146
|
+
{
|
147
|
+
relativeFilePath: "main-kc.tsx",
|
148
|
+
fileContent: [
|
149
|
+
`import { createRoot } from "react-dom/client";`,
|
150
|
+
`import { StrictMode } from "react";`,
|
151
|
+
`import { KcPage } from "./kc.gen";`,
|
152
|
+
``,
|
153
|
+
`if (!window.kcContext) {`,
|
154
|
+
` throw new Error("No Keycloak context");`,
|
155
|
+
`}`,
|
156
|
+
``,
|
157
|
+
`createRoot(document.getElementById("root")!).render(`,
|
158
|
+
` <StrictMode>`,
|
159
|
+
` <KcPage kcContext={window.kcContext} />`,
|
160
|
+
` </StrictMode>`,
|
161
|
+
`);`
|
162
|
+
].join("\n")
|
163
|
+
}
|
164
|
+
];
|
165
|
+
} else {
|
166
|
+
doAddRunDevScript = true;
|
167
|
+
|
168
|
+
await fs.copyFile(
|
169
|
+
mainTsxFilePath,
|
170
|
+
pathJoin(buildContext.themeSrcDirPath, "main-app.tsx")
|
171
|
+
);
|
172
|
+
|
173
|
+
files = [
|
174
|
+
{
|
175
|
+
relativeFilePath: "main.tsx",
|
176
|
+
fileContent: [
|
177
|
+
`if (window.kcContext !== undefined) {`,
|
178
|
+
` import("./keycloak-theme/main");`,
|
179
|
+
`} else if (import.meta.env.VITE_KC_DEV === "true") {`,
|
180
|
+
` import("./keycloak-theme/main.dev");`,
|
181
|
+
`} else {`,
|
182
|
+
` import("./main-app");`,
|
183
|
+
`}`,
|
184
|
+
``
|
185
|
+
].join("\n")
|
186
|
+
},
|
187
|
+
{
|
188
|
+
relativeFilePath: pathJoin(KEYCLOAK_THEME, "main.dev.tsx"),
|
189
|
+
fileContent: `export {};\n`
|
190
|
+
},
|
191
|
+
{
|
192
|
+
relativeFilePath: pathJoin(KEYCLOAK_THEME, "main.tsx"),
|
193
|
+
fileContent: [
|
194
|
+
`import { createRoot } from "react-dom/client";`,
|
195
|
+
`import { StrictMode } from "react";`,
|
196
|
+
`import { KcPage } from "./kc.gen";`,
|
197
|
+
``,
|
198
|
+
`if (!window.kcContext) {`,
|
199
|
+
` throw new Error("No Keycloak context");`,
|
200
|
+
`}`,
|
201
|
+
``,
|
202
|
+
`createRoot(document.getElementById("root")!).render(`,
|
203
|
+
` <StrictMode>`,
|
204
|
+
` <KcPage kcContext={window.kcContext} />`,
|
205
|
+
` </StrictMode>`,
|
206
|
+
`);`,
|
207
|
+
``
|
208
|
+
].join("\n")
|
209
|
+
}
|
210
|
+
];
|
211
|
+
}
|
212
|
+
|
213
|
+
for (let { relativeFilePath, fileContent } of files) {
|
214
|
+
const filePath = pathJoin(srcDirPath, relativeFilePath);
|
215
|
+
|
216
|
+
run_prettier: {
|
217
|
+
if (!(await getIsPrettierAvailable())) {
|
218
|
+
break run_prettier;
|
219
|
+
}
|
220
|
+
|
221
|
+
fileContent = await runPrettier({
|
222
|
+
filePath: filePath,
|
223
|
+
sourceCode: fileContent
|
224
|
+
});
|
225
|
+
}
|
226
|
+
|
227
|
+
await fs.writeFile(filePath, Buffer.from(fileContent, "utf8"));
|
228
|
+
}
|
229
|
+
}
|
230
|
+
|
231
|
+
add_script: {
|
232
|
+
const parsedPackageJson = await (async () => {
|
233
|
+
type ParsedPackageJson = {
|
234
|
+
scripts: Record<string, string>;
|
235
|
+
};
|
236
|
+
|
237
|
+
const zParsedPackageJson = (() => {
|
238
|
+
type TargetType = ParsedPackageJson;
|
239
|
+
|
240
|
+
const zTargetType = z.object({
|
241
|
+
scripts: z.record(z.string(), z.string())
|
242
|
+
});
|
243
|
+
|
244
|
+
assert<Equals<z.infer<typeof zTargetType>, TargetType>>();
|
245
|
+
|
246
|
+
return id<z.ZodType<TargetType>>(zTargetType);
|
247
|
+
})();
|
248
|
+
|
249
|
+
const parsedPackageJson = JSON.parse(
|
250
|
+
(await fs.readFile(buildContext.packageJsonFilePath)).toString("utf8")
|
251
|
+
);
|
252
|
+
|
253
|
+
zParsedPackageJson.parse(parsedPackageJson);
|
254
|
+
|
255
|
+
assert(is<ParsedPackageJson>(parsedPackageJson));
|
256
|
+
|
257
|
+
return parsedPackageJson;
|
258
|
+
})();
|
259
|
+
|
260
|
+
const SCRIPT_NAME = "build-keycloak-theme";
|
261
|
+
|
262
|
+
if (SCRIPT_NAME in parsedPackageJson.scripts) {
|
263
|
+
break add_script;
|
264
|
+
}
|
265
|
+
|
266
|
+
parsedPackageJson.scripts[SCRIPT_NAME] = "npm run build && keycloakify build";
|
267
|
+
if (doAddRunDevScript) {
|
268
|
+
parsedPackageJson.scripts["dev-keycloak-theme"] =
|
269
|
+
"VITE_KC_DEV=true npm run dev";
|
270
|
+
}
|
271
|
+
|
272
|
+
let packageJson_content = JSON.stringify(parsedPackageJson, null, 2);
|
273
|
+
|
274
|
+
run_prettier: {
|
275
|
+
if (!(await getIsPrettierAvailable())) {
|
276
|
+
break run_prettier;
|
277
|
+
}
|
278
|
+
|
279
|
+
packageJson_content = await runPrettier({
|
280
|
+
filePath: buildContext.packageJsonFilePath,
|
281
|
+
sourceCode: packageJson_content
|
282
|
+
});
|
283
|
+
}
|
284
|
+
|
285
|
+
await fs.writeFile(
|
286
|
+
buildContext.packageJsonFilePath,
|
287
|
+
Buffer.from(packageJson_content, "utf8")
|
288
|
+
);
|
289
|
+
}
|
290
|
+
|
291
|
+
const themeType = await (async () => {
|
292
|
+
const values = ([...THEME_TYPES, "email"] as const).filter(themeType => {
|
293
|
+
const wrap = buildContext.implementedThemeTypes[themeType];
|
294
|
+
|
295
|
+
return !wrap.isImplemented && !wrap.isImplemented_native;
|
296
|
+
});
|
297
|
+
|
298
|
+
if (values.length === 0) {
|
299
|
+
return undefined;
|
300
|
+
}
|
301
|
+
|
302
|
+
console.log(chalk.cyan(`\nWhich theme theme type would you like to initialize?`));
|
303
|
+
|
304
|
+
const { value } = await cliSelect({
|
305
|
+
values
|
306
|
+
}).catch(() => {
|
307
|
+
process.exit(-1);
|
308
|
+
});
|
309
|
+
|
310
|
+
console.log(value);
|
311
|
+
|
312
|
+
return value;
|
313
|
+
})();
|
314
|
+
|
315
|
+
if (themeType === undefined) {
|
316
|
+
console.log(
|
317
|
+
chalk.gray("You already have implemented a theme type of every kind, exiting")
|
318
|
+
);
|
319
|
+
process.exit(0);
|
320
|
+
}
|
321
|
+
|
322
|
+
switch (themeType) {
|
323
|
+
case "account":
|
324
|
+
{
|
325
|
+
const { command } = await import("../initialize-account-theme");
|
326
|
+
|
327
|
+
await command({ buildContext });
|
328
|
+
}
|
329
|
+
return;
|
330
|
+
case "admin":
|
331
|
+
{
|
332
|
+
const { command } = await import("../initialize-admin-theme");
|
333
|
+
|
334
|
+
await command({ buildContext });
|
335
|
+
}
|
336
|
+
return;
|
337
|
+
case "email":
|
338
|
+
{
|
339
|
+
const { command } = await import("../initialize-email-theme");
|
340
|
+
|
341
|
+
await command({ buildContext });
|
342
|
+
}
|
343
|
+
return;
|
344
|
+
case "login":
|
345
|
+
{
|
346
|
+
const { command } = await import("../initialize-login-theme");
|
347
|
+
|
348
|
+
await command({ buildContext });
|
349
|
+
}
|
350
|
+
return;
|
351
|
+
}
|
352
|
+
|
353
|
+
assert<Equals<typeof themeType, never>>;
|
354
|
+
}
|
@@ -0,0 +1,80 @@
|
|
1
|
+
import { join as pathJoin } from "path";
|
2
|
+
import { existsAsync } from "../tools/fs.existsAsync";
|
3
|
+
import * as fs from "fs/promises";
|
4
|
+
import * as recast from "recast";
|
5
|
+
import { runPrettier, getIsPrettierAvailable } from "../tools/runPrettier";
|
6
|
+
import * as babelParser from "@babel/parser";
|
7
|
+
import babelGenerate from "@babel/generator";
|
8
|
+
import * as babelTypes from "@babel/types";
|
9
|
+
|
10
|
+
/** This function will just set reportUnusedDisableDirectives to off so that we don't get warning on generated files */
|
11
|
+
export async function setupEslint(params: { projectDirPath: string }) {
|
12
|
+
const { projectDirPath } = params;
|
13
|
+
|
14
|
+
const eslintConfigJsFilePath = pathJoin(projectDirPath, "eslint.config.js");
|
15
|
+
|
16
|
+
if (!(await existsAsync(eslintConfigJsFilePath))) {
|
17
|
+
return;
|
18
|
+
}
|
19
|
+
|
20
|
+
const eslintConfigJsContent = (await fs.readFile(eslintConfigJsFilePath)).toString(
|
21
|
+
"utf8"
|
22
|
+
);
|
23
|
+
|
24
|
+
if (eslintConfigJsContent.includes("reportUnusedDisableDirectives")) {
|
25
|
+
return;
|
26
|
+
}
|
27
|
+
|
28
|
+
const root = recast.parse(eslintConfigJsContent, {
|
29
|
+
parser: {
|
30
|
+
parse: (code: string) =>
|
31
|
+
babelParser.parse(code, {
|
32
|
+
sourceType: "module",
|
33
|
+
plugins: ["typescript"]
|
34
|
+
})
|
35
|
+
}
|
36
|
+
});
|
37
|
+
|
38
|
+
recast.visit(root, {
|
39
|
+
visitExportDefaultDeclaration(path) {
|
40
|
+
// @ts-expect-error
|
41
|
+
const args = path.node.declaration.arguments;
|
42
|
+
|
43
|
+
if (!Array.isArray(args)) return false;
|
44
|
+
|
45
|
+
args.push(
|
46
|
+
babelTypes.objectExpression([
|
47
|
+
babelTypes.objectProperty(
|
48
|
+
babelTypes.identifier("linterOptions"),
|
49
|
+
babelTypes.objectExpression([
|
50
|
+
babelTypes.objectProperty(
|
51
|
+
babelTypes.identifier("reportUnusedDisableDirectives"),
|
52
|
+
babelTypes.stringLiteral("off")
|
53
|
+
)
|
54
|
+
])
|
55
|
+
)
|
56
|
+
])
|
57
|
+
);
|
58
|
+
|
59
|
+
return false;
|
60
|
+
}
|
61
|
+
});
|
62
|
+
|
63
|
+
let eslintConfigJsContent_modified = babelGenerate(root).code;
|
64
|
+
|
65
|
+
format: {
|
66
|
+
if (!(await getIsPrettierAvailable())) {
|
67
|
+
break format;
|
68
|
+
}
|
69
|
+
|
70
|
+
eslintConfigJsContent_modified = await runPrettier({
|
71
|
+
sourceCode: eslintConfigJsContent_modified,
|
72
|
+
filePath: eslintConfigJsFilePath
|
73
|
+
});
|
74
|
+
}
|
75
|
+
|
76
|
+
await fs.writeFile(
|
77
|
+
eslintConfigJsFilePath,
|
78
|
+
Buffer.from(eslintConfigJsContent_modified, "utf8")
|
79
|
+
);
|
80
|
+
}
|
@@ -0,0 +1,143 @@
|
|
1
|
+
import { join as pathJoin } from "path";
|
2
|
+
import { existsAsync } from "../tools/fs.existsAsync";
|
3
|
+
import * as fs from "fs/promises";
|
4
|
+
import * as recast from "recast";
|
5
|
+
import { runPrettier, getIsPrettierAvailable } from "../tools/runPrettier";
|
6
|
+
import * as babelParser from "@babel/parser";
|
7
|
+
import babelGenerate from "@babel/generator";
|
8
|
+
import * as babelTypes from "@babel/types";
|
9
|
+
|
10
|
+
/** Best effort to setup the Keycloakify vite plugin automatically */
|
11
|
+
export async function setupVitePluginIfNeeded(params: { projectDirPath: string }) {
|
12
|
+
const { projectDirPath } = params;
|
13
|
+
|
14
|
+
const viteConfigTsFilePath = pathJoin(projectDirPath, "vite.config.ts");
|
15
|
+
|
16
|
+
if (!(await existsAsync(viteConfigTsFilePath))) {
|
17
|
+
return;
|
18
|
+
}
|
19
|
+
|
20
|
+
const viteConfigTsContent = (await fs.readFile(viteConfigTsFilePath)).toString(
|
21
|
+
"utf8"
|
22
|
+
);
|
23
|
+
|
24
|
+
if (viteConfigTsContent.includes("keycloakify")) {
|
25
|
+
return;
|
26
|
+
}
|
27
|
+
|
28
|
+
const root = recast.parse(viteConfigTsContent, {
|
29
|
+
parser: {
|
30
|
+
parse: (code: string) =>
|
31
|
+
babelParser.parse(code, {
|
32
|
+
sourceType: "module",
|
33
|
+
plugins: ["typescript"]
|
34
|
+
}),
|
35
|
+
generator: babelGenerate,
|
36
|
+
types: babelTypes
|
37
|
+
}
|
38
|
+
});
|
39
|
+
|
40
|
+
/* Before:
|
41
|
+
import { defineConfig } from "vite";
|
42
|
+
import react from "@vitejs/plugin-react";
|
43
|
+
|
44
|
+
// https://vitejs.dev/config/
|
45
|
+
export default defineConfig({
|
46
|
+
plugins: [ react() ]
|
47
|
+
});
|
48
|
+
*/
|
49
|
+
|
50
|
+
/* After:
|
51
|
+
import { defineConfig } from "vite";
|
52
|
+
import react from "@vitejs/plugin-react";
|
53
|
+
import { keycloakify } from "keycloakify/vite-plugin";
|
54
|
+
|
55
|
+
// https://vitejs.dev/config/
|
56
|
+
export default defineConfig({
|
57
|
+
plugins: [
|
58
|
+
react(),
|
59
|
+
keycloakify({
|
60
|
+
accountThemeImplementation: "none"
|
61
|
+
})
|
62
|
+
]
|
63
|
+
});
|
64
|
+
*/
|
65
|
+
|
66
|
+
recast.visit(root, {
|
67
|
+
visitProgram(path) {
|
68
|
+
const body = path.node.body;
|
69
|
+
|
70
|
+
// Add import: import { keycloakify } from "keycloakify/vite-plugin";
|
71
|
+
const importDeclaration = babelTypes.importDeclaration(
|
72
|
+
[
|
73
|
+
babelTypes.importSpecifier(
|
74
|
+
babelTypes.identifier("keycloakify"),
|
75
|
+
babelTypes.identifier("keycloakify")
|
76
|
+
)
|
77
|
+
],
|
78
|
+
babelTypes.stringLiteral("keycloakify/vite-plugin")
|
79
|
+
);
|
80
|
+
// @ts-expect-error
|
81
|
+
body.unshift(importDeclaration);
|
82
|
+
|
83
|
+
this.traverse(path);
|
84
|
+
},
|
85
|
+
visitCallExpression(path) {
|
86
|
+
const { node } = path;
|
87
|
+
|
88
|
+
if (
|
89
|
+
// @ts-expect-error
|
90
|
+
babelTypes.isIdentifier(node.callee, { name: "defineConfig" }) &&
|
91
|
+
node.arguments.length === 1 &&
|
92
|
+
// @ts-expect-error
|
93
|
+
babelTypes.isObjectExpression(node.arguments[0])
|
94
|
+
) {
|
95
|
+
const configObject = node.arguments[0];
|
96
|
+
const pluginsProp = configObject.properties.find(
|
97
|
+
prop =>
|
98
|
+
// @ts-expect-error
|
99
|
+
babelTypes.isObjectProperty(prop) &&
|
100
|
+
babelTypes.isIdentifier(prop.key, { name: "plugins" }) &&
|
101
|
+
babelTypes.isArrayExpression(prop.value)
|
102
|
+
) as babelTypes.ObjectProperty | undefined;
|
103
|
+
|
104
|
+
if (pluginsProp && babelTypes.isArrayExpression(pluginsProp.value)) {
|
105
|
+
// Append keycloakify plugin config
|
106
|
+
const keycloakifyCall = babelTypes.callExpression(
|
107
|
+
babelTypes.identifier("keycloakify"),
|
108
|
+
[
|
109
|
+
babelTypes.objectExpression([
|
110
|
+
babelTypes.objectProperty(
|
111
|
+
babelTypes.identifier("accountThemeImplementation"),
|
112
|
+
babelTypes.stringLiteral("none")
|
113
|
+
)
|
114
|
+
])
|
115
|
+
]
|
116
|
+
);
|
117
|
+
|
118
|
+
pluginsProp.value.elements.push(keycloakifyCall);
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
this.traverse(path);
|
123
|
+
}
|
124
|
+
});
|
125
|
+
|
126
|
+
let viteConfigTsContent_modified = babelGenerate(root).code;
|
127
|
+
|
128
|
+
format: {
|
129
|
+
if (!(await getIsPrettierAvailable())) {
|
130
|
+
break format;
|
131
|
+
}
|
132
|
+
|
133
|
+
viteConfigTsContent_modified = await runPrettier({
|
134
|
+
sourceCode: viteConfigTsContent_modified,
|
135
|
+
filePath: viteConfigTsFilePath
|
136
|
+
});
|
137
|
+
}
|
138
|
+
|
139
|
+
await fs.writeFile(
|
140
|
+
viteConfigTsFilePath,
|
141
|
+
Buffer.from(viteConfigTsContent_modified, "utf8")
|
142
|
+
);
|
143
|
+
}
|
@@ -26,12 +26,16 @@ export async function command(params: { buildContext: BuildContext }) {
|
|
26
26
|
projectDirPath: buildContext.projectDirPath
|
27
27
|
});
|
28
28
|
|
29
|
+
console.log(chalk.cyan("Which account theme type?"));
|
30
|
+
|
29
31
|
const { value: accountThemeType } = await cliSelect({
|
30
32
|
values: ["Single-Page" as const, "Multi-Page" as const]
|
31
33
|
}).catch(() => {
|
32
34
|
process.exit(-1);
|
33
35
|
});
|
34
36
|
|
37
|
+
console.log(`${accountThemeType}\n`);
|
38
|
+
|
35
39
|
switch (accountThemeType) {
|
36
40
|
case "Multi-Page":
|
37
41
|
{
|