keycloakify 11.8.46 → 11.8.47-rc.2

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.
Files changed (43) hide show
  1. package/bin/254.index.js +283 -0
  2. package/bin/30.index.js +25 -0
  3. package/bin/{864.index.js → 309.index.js} +6944 -28439
  4. package/bin/311.index.js +198 -0
  5. package/bin/{313.index.js → 355.index.js} +148 -172
  6. package/bin/{84.index.js → 502.index.js} +151 -103
  7. package/bin/626.index.js +216 -0
  8. package/bin/656.index.js +274 -0
  9. package/bin/675.index.js +177 -0
  10. package/bin/69.index.js +1 -1
  11. package/bin/762.index.js +1475 -0
  12. package/bin/780.index.js +4 -2
  13. package/bin/786.index.js +115 -0
  14. package/bin/895.index.js +21501 -0
  15. package/bin/{618.index.js → 932.index.js} +117 -163
  16. package/bin/949.index.js +1 -1
  17. package/bin/97.index.js +539 -4
  18. package/bin/init/index.d.ts +1 -0
  19. package/bin/init/init.d.ts +3 -0
  20. package/bin/init/setupEslint.d.ts +4 -0
  21. package/bin/init/setupVitePluginIfNeeded.d.ts +4 -0
  22. package/bin/initialize-login-theme.d.ts +4 -0
  23. package/bin/main.js +42 -49
  24. package/bin/shared/customHandler.d.ts +1 -1
  25. package/bin/shared/customHandler.js.map +1 -1
  26. package/package.json +23 -7
  27. package/src/bin/init/index.ts +1 -0
  28. package/src/bin/init/init.ts +354 -0
  29. package/src/bin/init/setupEslint.ts +80 -0
  30. package/src/bin/init/setupVitePluginIfNeeded.ts +143 -0
  31. package/src/bin/initialize-account-theme/initialize-account-theme.ts +4 -0
  32. package/src/bin/initialize-login-theme.ts +323 -0
  33. package/src/bin/main.ts +14 -0
  34. package/src/bin/shared/buildContext.ts +28 -59
  35. package/src/bin/shared/customHandler.ts +3 -1
  36. package/src/bin/shared/initializeSpa.ts +28 -0
  37. package/src/bin/sync-extensions/extensionModuleMeta.ts +89 -73
  38. package/src/bin/sync-extensions/managedGitignoreFiles.ts +32 -2
  39. package/src/bin/tools/fetchProxyOptions.ts +2 -1
  40. package/src/bin/tools/npmInstall.ts +13 -6
  41. package/vite-plugin/index.js +24 -43
  42. package/bin/433.index.js +0 -140
  43. package/bin/698.index.js +0 -298
package/bin/main.js CHANGED
@@ -73,7 +73,8 @@ function getProxyFetchOptions(params) {
73
73
  const { npmConfigGetCwd } = params;
74
74
  const cfg = (() => {
75
75
  const output = external_child_process_.execSync("npm config get", {
76
- cwd: npmConfigGetCwd
76
+ cwd: npmConfigGetCwd,
77
+ stdio: ["pipe", "pipe", "ignore"]
77
78
  })
78
79
  .toString("utf8");
79
80
  return output
@@ -194,30 +195,7 @@ function getBuildContext(params) {
194
195
  if (themeSrcDirPath !== undefined) {
195
196
  return { themeSrcDirPath };
196
197
  }
197
- {
198
- const basenames = external_fs_.readdirSync(srcDirPath);
199
- for (const basename of basenames) {
200
- const path = (0,external_path_.join)(srcDirPath, basename);
201
- if (!external_fs_.statSync(path).isFile()) {
202
- continue;
203
- }
204
- if (external_fs_.readFileSync(path).toString("utf8").includes("./kc.gen")) {
205
- return { themeSrcDirPath: srcDirPath };
206
- }
207
- }
208
- }
209
- for (const themeType of [...constants/* THEME_TYPES */.Jh, "email"]) {
210
- if (!external_fs_.existsSync((0,external_path_.join)(srcDirPath, themeType))) {
211
- continue;
212
- }
213
- return { themeSrcDirPath: srcDirPath };
214
- }
215
- console.log(source_default().red([
216
- `Can't locate your Keycloak theme source directory in .${external_path_.sep}${(0,external_path_.relative)(process.cwd(), srcDirPath)}`,
217
- `Make sure to either use the Keycloakify CLI in the root of your Keycloakify project or use the --project CLI option`,
218
- `If you are collocating your Keycloak theme with your app you must have a directory named '${constants/* KEYCLOAK_THEME */.PC}' or '${constants/* KEYCLOAK_THEME.replace */.PC.replace(/-/g, "_")}' in your 'src' directory`
219
- ].join("\n")));
220
- process.exit(1);
198
+ return { themeSrcDirPath: srcDirPath };
221
199
  })();
222
200
  const { resolvedViteConfig } = (() => {
223
201
  if (external_fs_.readdirSync(projectDirPath)
@@ -227,6 +205,7 @@ function getBuildContext(params) {
227
205
  }
228
206
  const output = external_child_process_.execSync("npx vite", {
229
207
  cwd: projectDirPath,
208
+ stdio: ["pipe", "pipe", "ignore"],
230
209
  env: Object.assign(Object.assign({}, process.env), { [constants/* VITE_PLUGIN_SUB_SCRIPTS_ENV_NAMES.RESOLVE_VITE_CONFIG */.TE.RESOLVE_VITE_CONFIG]: "true" })
231
210
  })
232
211
  .toString("utf8");
@@ -600,25 +579,27 @@ function getBuildContext(params) {
600
579
  environmentVariables: (_e = buildOptions.environmentVariables) !== null && _e !== void 0 ? _e : [],
601
580
  implementedThemeTypes,
602
581
  themeSrcDirPath,
603
- fetchOptions: getProxyFetchOptions({
604
- npmConfigGetCwd: (function callee(upCount) {
605
- const dirPath = (0,external_path_.resolve)((0,external_path_.join)(...[projectDirPath, ...Array(upCount).fill("..")]));
606
- (0,assert/* assert */.h)(dirPath !== external_path_.sep, "Couldn't find a place to run 'npm config get'");
607
- try {
608
- external_child_process_.execSync("npm config get", {
609
- cwd: dirPath,
610
- stdio: "pipe"
611
- });
612
- }
613
- catch (error) {
614
- if (String(error).includes("ENOWORKSPACES")) {
615
- return callee(upCount + 1);
582
+ get fetchOptions() {
583
+ return getProxyFetchOptions({
584
+ npmConfigGetCwd: (function callee(upCount) {
585
+ const dirPath = (0,external_path_.resolve)((0,external_path_.join)(...[projectDirPath, ...Array(upCount).fill("..")]));
586
+ (0,assert/* assert */.h)(dirPath !== external_path_.sep, "Couldn't find a place to run 'npm config get'");
587
+ try {
588
+ external_child_process_.execSync("npm config get", {
589
+ cwd: dirPath,
590
+ stdio: "pipe"
591
+ });
616
592
  }
617
- throw error;
618
- }
619
- return dirPath;
620
- })(0)
621
- }),
593
+ catch (error) {
594
+ if (String(error).includes("ENOWORKSPACES")) {
595
+ return callee(upCount + 1);
596
+ }
597
+ throw error;
598
+ }
599
+ return dirPath;
600
+ })(0)
601
+ });
602
+ },
622
603
  jarTargets: (() => {
623
604
  const getDefaultJarFileBasename = (range) => `keycloak-theme-for-kc-${range}.jar`;
624
605
  build_for_specific_keycloak_major_version: {
@@ -16223,7 +16204,7 @@ program
16223
16204
  .task({
16224
16205
  skip,
16225
16206
  handler: async ({ projectDirPath }) => {
16226
- const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(864), __nccwpck_require__.e(712)]).then(__nccwpck_require__.bind(__nccwpck_require__, 35712));
16207
+ const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(309), __nccwpck_require__.e(895), __nccwpck_require__.e(712)]).then(__nccwpck_require__.bind(__nccwpck_require__, 35712));
16227
16208
  await command({ buildContext: (0,buildContext/* getBuildContext */.s)({ projectDirPath }) });
16228
16209
  }
16229
16210
  });
@@ -16282,6 +16263,18 @@ program
16282
16263
  });
16283
16264
  }
16284
16265
  });
16266
+ program
16267
+ .command({
16268
+ name: "init",
16269
+ description: "(BETA) Initialize a new theme type (login/account/admin/email)"
16270
+ })
16271
+ .task({
16272
+ skip,
16273
+ handler: async ({ projectDirPath }) => {
16274
+ const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(309), __nccwpck_require__.e(762)]).then(__nccwpck_require__.bind(__nccwpck_require__, 70762));
16275
+ await command({ projectDirPath: projectDirPath !== null && projectDirPath !== void 0 ? projectDirPath : process.cwd() });
16276
+ }
16277
+ });
16285
16278
  program
16286
16279
  .command({
16287
16280
  name: "eject-page",
@@ -16314,7 +16307,7 @@ program
16314
16307
  .task({
16315
16308
  skip,
16316
16309
  handler: async ({ projectDirPath }) => {
16317
- const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(84), __nccwpck_require__.e(618)]).then(__nccwpck_require__.bind(__nccwpck_require__, 16932));
16310
+ const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(502), __nccwpck_require__.e(932)]).then(__nccwpck_require__.bind(__nccwpck_require__, 16932));
16318
16311
  await command({ buildContext: (0,buildContext/* getBuildContext */.s)({ projectDirPath }) });
16319
16312
  }
16320
16313
  });
@@ -16338,7 +16331,7 @@ program
16338
16331
  .task({
16339
16332
  skip,
16340
16333
  handler: async ({ projectDirPath }) => {
16341
- const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(84), __nccwpck_require__.e(313)]).then(__nccwpck_require__.bind(__nccwpck_require__, 60355));
16334
+ const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(502), __nccwpck_require__.e(355)]).then(__nccwpck_require__.bind(__nccwpck_require__, 60355));
16342
16335
  await command({ buildContext: (0,buildContext/* getBuildContext */.s)({ projectDirPath }) });
16343
16336
  }
16344
16337
  });
@@ -16362,7 +16355,7 @@ program
16362
16355
  .task({
16363
16356
  skip,
16364
16357
  handler: async ({ projectDirPath }) => {
16365
- const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(786), __nccwpck_require__.e(433)]).then(__nccwpck_require__.bind(__nccwpck_require__, 10786));
16358
+ const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(786), __nccwpck_require__.e(30)]).then(__nccwpck_require__.bind(__nccwpck_require__, 10786));
16366
16359
  await command({ buildContext: (0,buildContext/* getBuildContext */.s)({ projectDirPath }) });
16367
16360
  }
16368
16361
  });
@@ -16391,7 +16384,7 @@ program
16391
16384
  .task({
16392
16385
  skip,
16393
16386
  handler: async ({ projectDirPath }) => {
16394
- const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(69), __nccwpck_require__.e(84), __nccwpck_require__.e(786), __nccwpck_require__.e(97), __nccwpck_require__.e(946)]).then(__nccwpck_require__.bind(__nccwpck_require__, 74946));
16387
+ const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(69), __nccwpck_require__.e(786), __nccwpck_require__.e(97), __nccwpck_require__.e(946)]).then(__nccwpck_require__.bind(__nccwpck_require__, 74946));
16395
16388
  await command({ buildContext: (0,buildContext/* getBuildContext */.s)({ projectDirPath }) });
16396
16389
  }
16397
16390
  });
@@ -16459,7 +16452,7 @@ program
16459
16452
  .task({
16460
16453
  skip,
16461
16454
  handler: async ({ projectDirPath, path, revert, public: public_params }) => {
16462
- const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(69), __nccwpck_require__.e(84), __nccwpck_require__.e(786), __nccwpck_require__.e(97), __nccwpck_require__.e(930)]).then(__nccwpck_require__.bind(__nccwpck_require__, 71930));
16455
+ const { command } = await Promise.all(/* import() */[__nccwpck_require__.e(69), __nccwpck_require__.e(786), __nccwpck_require__.e(97), __nccwpck_require__.e(930)]).then(__nccwpck_require__.bind(__nccwpck_require__, 71930));
16463
16456
  await command({
16464
16457
  buildContext: (0,buildContext/* getBuildContext */.s)({ projectDirPath }),
16465
16458
  cliCommandOptions: { path, isRevert: revert, isPublic: public_params }
@@ -1,7 +1,7 @@
1
1
  import type { BuildContext } from "./buildContext";
2
2
  export declare const BIN_NAME = "_keycloakify-custom-handler";
3
3
  export declare const NOT_IMPLEMENTED_EXIT_CODE = 78;
4
- export type CommandName = "update-kc-gen" | "eject-page" | "add-story" | "initialize-account-theme" | "initialize-admin-theme" | "initialize-admin-theme" | "initialize-email-theme" | "copy-keycloak-resources-to-public";
4
+ export type CommandName = "update-kc-gen" | "eject-page" | "add-story" | "initialize-login-theme" | "initialize-account-theme" | "initialize-admin-theme" | "initialize-admin-theme" | "initialize-email-theme" | "copy-keycloak-resources-to-public" | "init";
5
5
  export type ApiVersion = "v1";
6
6
  export declare function readParams(params: {
7
7
  apiVersion: ApiVersion;
@@ -1 +1 @@
1
- {"version":3,"file":"customHandler.js","sourceRoot":"","sources":["../../src/bin/shared/customHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAEvD,MAAM,CAAC,MAAM,QAAQ,GAAG,6BAA6B,CAAC;AAEtD,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAc5C,MAAM,UAAU,UAAU,CAAC,MAAkC;IACzD,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC;IAE9B,MAAM,CAAC,UAAU,KAAK,IAAI,CAAC,CAAC;IAE5B,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE;QACtB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,YAAY,CAAC,CAAC;QAEpE,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC;QAE/B,OAAO,QAAuB,CAAC;IACnC,CAAC,CAAC,EAAE,CAAC;IAEL,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE;QACvB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,aAAa,CAAC,CAAC;QAErE,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC;QAE/B,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAiB,CAAC;IAChD,CAAC,CAAC,EAAE,CAAC;IAEL,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;AACzC,CAAC"}
1
+ {"version":3,"file":"customHandler.js","sourceRoot":"","sources":["../../src/bin/shared/customHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAEvD,MAAM,CAAC,MAAM,QAAQ,GAAG,6BAA6B,CAAC;AAEtD,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAgB5C,MAAM,UAAU,UAAU,CAAC,MAAkC;IACzD,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC;IAE9B,MAAM,CAAC,UAAU,KAAK,IAAI,CAAC,CAAC;IAE5B,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE;QACtB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,YAAY,CAAC,CAAC;QAEpE,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC;QAE/B,OAAO,QAAuB,CAAC;IACnC,CAAC,CAAC,EAAE,CAAC;IAEL,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE;QACvB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,aAAa,CAAC,CAAC;QAErE,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC;QAE/B,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAiB,CAAC;IAChD,CAAC,CAAC,EAAE,CAAC;IAEL,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;AACzC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keycloakify",
3
- "version": "11.8.46",
3
+ "version": "11.8.47-rc.2",
4
4
  "description": "Framework to create custom Keycloak UIs",
5
5
  "repository": {
6
6
  "type": "git",
@@ -655,6 +655,10 @@
655
655
  "src/bin/add-story.ts",
656
656
  "src/bin/copy-keycloak-resources-to-public.ts",
657
657
  "src/bin/eject-page.ts",
658
+ "src/bin/init/index.ts",
659
+ "src/bin/init/init.ts",
660
+ "src/bin/init/setupEslint.ts",
661
+ "src/bin/init/setupVitePluginIfNeeded.ts",
658
662
  "src/bin/initialize-account-theme/index.ts",
659
663
  "src/bin/initialize-account-theme/initialize-account-theme.ts",
660
664
  "src/bin/initialize-account-theme/multi-page-boilerplate/KcContext.ts",
@@ -664,6 +668,7 @@
664
668
  "src/bin/initialize-account-theme/updateAccountThemeImplementationInConfig.ts",
665
669
  "src/bin/initialize-admin-theme.ts",
666
670
  "src/bin/initialize-email-theme.ts",
671
+ "src/bin/initialize-login-theme.ts",
667
672
  "src/bin/keycloakify/buildJars/buildJar.ts",
668
673
  "src/bin/keycloakify/buildJars/buildJars.ts",
669
674
  "src/bin/keycloakify/buildJars/extensionVersions.ts",
@@ -1034,11 +1039,16 @@
1034
1039
  "bin/add-story.d.ts",
1035
1040
  "bin/copy-keycloak-resources-to-public.d.ts",
1036
1041
  "bin/eject-page.d.ts",
1042
+ "bin/init/index.d.ts",
1043
+ "bin/init/init.d.ts",
1044
+ "bin/init/setupEslint.d.ts",
1045
+ "bin/init/setupVitePluginIfNeeded.d.ts",
1037
1046
  "bin/initialize-account-theme/index.d.ts",
1038
1047
  "bin/initialize-account-theme/initialize-account-theme.d.ts",
1039
1048
  "bin/initialize-account-theme/updateAccountThemeImplementationInConfig.d.ts",
1040
1049
  "bin/initialize-admin-theme.d.ts",
1041
1050
  "bin/initialize-email-theme.d.ts",
1051
+ "bin/initialize-login-theme.d.ts",
1042
1052
  "bin/keycloakify/buildJars/buildJar.d.ts",
1043
1053
  "bin/keycloakify/buildJars/buildJars.d.ts",
1044
1054
  "bin/keycloakify/buildJars/extensionVersions.d.ts",
@@ -1122,27 +1132,33 @@
1122
1132
  "bin/tools/transformCodebase.d.ts",
1123
1133
  "bin/update-kc-gen.d.ts",
1124
1134
  "bin/main.js",
1135
+ "bin/254.index.js",
1125
1136
  "bin/266.index.js",
1137
+ "bin/30.index.js",
1126
1138
  "bin/304.index.js",
1127
- "bin/313.index.js",
1139
+ "bin/309.index.js",
1140
+ "bin/311.index.js",
1141
+ "bin/355.index.js",
1128
1142
  "bin/369.index.js",
1129
1143
  "bin/375.index.js",
1130
1144
  "bin/40.index.js",
1131
- "bin/433.index.js",
1132
1145
  "bin/453.index.js",
1133
- "bin/618.index.js",
1146
+ "bin/502.index.js",
1147
+ "bin/626.index.js",
1148
+ "bin/656.index.js",
1134
1149
  "bin/658.index.js",
1150
+ "bin/675.index.js",
1135
1151
  "bin/69.index.js",
1136
- "bin/698.index.js",
1137
1152
  "bin/712.index.js",
1138
1153
  "bin/720.index.js",
1154
+ "bin/762.index.js",
1139
1155
  "bin/780.index.js",
1140
1156
  "bin/786.index.js",
1141
- "bin/84.index.js",
1142
- "bin/864.index.js",
1143
1157
  "bin/877.index.js",
1158
+ "bin/895.index.js",
1144
1159
  "bin/910.index.js",
1145
1160
  "bin/930.index.js",
1161
+ "bin/932.index.js",
1146
1162
  "bin/946.index.js",
1147
1163
  "bin/949.index.js",
1148
1164
  "bin/97.index.js",
@@ -0,0 +1 @@
1
+ export * from "./init";
@@ -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(`Which 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
+ }