keycloakify 10.0.0-rc.18 → 10.0.0-rc.19

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/main.js CHANGED
@@ -4832,6 +4832,207 @@ exports.promptKeycloakVersion = promptKeycloakVersion;
4832
4832
 
4833
4833
  /***/ }),
4834
4834
 
4835
+ /***/ 18170:
4836
+ /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
4837
+
4838
+ "use strict";
4839
+
4840
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4841
+ if (k2 === undefined) k2 = k;
4842
+ var desc = Object.getOwnPropertyDescriptor(m, k);
4843
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
4844
+ desc = { enumerable: true, get: function() { return m[k]; } };
4845
+ }
4846
+ Object.defineProperty(o, k2, desc);
4847
+ }) : (function(o, m, k, k2) {
4848
+ if (k2 === undefined) k2 = k;
4849
+ o[k2] = m[k];
4850
+ }));
4851
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
4852
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
4853
+ }) : function(o, v) {
4854
+ o["default"] = v;
4855
+ });
4856
+ var __importStar = (this && this.__importStar) || function (mod) {
4857
+ if (mod && mod.__esModule) return mod;
4858
+ var result = {};
4859
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
4860
+ __setModuleDefault(result, mod);
4861
+ return result;
4862
+ };
4863
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4864
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4865
+ return new (P || (P = Promise))(function (resolve, reject) {
4866
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
4867
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
4868
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
4869
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
4870
+ });
4871
+ };
4872
+ var __generator = (this && this.__generator) || function (thisArg, body) {
4873
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
4874
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
4875
+ function verb(n) { return function (v) { return step([n, v]); }; }
4876
+ function step(op) {
4877
+ if (f) throw new TypeError("Generator is already executing.");
4878
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
4879
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
4880
+ if (y = 0, t) op = [op[0] & 2, t.value];
4881
+ switch (op[0]) {
4882
+ case 0: case 1: t = op; break;
4883
+ case 4: _.label++; return { value: op[1], done: false };
4884
+ case 5: _.label++; y = op[1]; op = [0]; continue;
4885
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
4886
+ default:
4887
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
4888
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
4889
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
4890
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
4891
+ if (t[2]) _.ops.pop();
4892
+ _.trys.pop(); continue;
4893
+ }
4894
+ op = body.call(thisArg, _);
4895
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
4896
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
4897
+ }
4898
+ };
4899
+ var __values = (this && this.__values) || function(o) {
4900
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
4901
+ if (m) return m.call(o);
4902
+ if (o && typeof o.length === "number") return {
4903
+ next: function () {
4904
+ if (o && i >= o.length) o = void 0;
4905
+ return { value: o && o[i++], done: !o };
4906
+ }
4907
+ };
4908
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
4909
+ };
4910
+ var __read = (this && this.__read) || function (o, n) {
4911
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
4912
+ if (!m) return o;
4913
+ var i = m.call(o), r, ar = [], e;
4914
+ try {
4915
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
4916
+ }
4917
+ catch (error) { e = { error: error }; }
4918
+ finally {
4919
+ try {
4920
+ if (r && !r.done && (m = i["return"])) m.call(i);
4921
+ }
4922
+ finally { if (e) throw e.error; }
4923
+ }
4924
+ return ar;
4925
+ };
4926
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
4927
+ exports.appBuild = void 0;
4928
+ var child_process = __importStar(__nccwpck_require__(32081));
4929
+ var Deferred_1 = __nccwpck_require__(50689);
4930
+ var assert_1 = __nccwpck_require__(88078);
4931
+ var is_1 = __nccwpck_require__(94655);
4932
+ var fs = __importStar(__nccwpck_require__(57147));
4933
+ var path_1 = __nccwpck_require__(71017);
4934
+ (0, assert_1.assert)();
4935
+ function appBuild(params) {
4936
+ return __awaiter(this, void 0, void 0, function () {
4937
+ var doSkipIfReactAppBuildDirExists, buildOptions, bundler, _a, command, args, cwd, dResult, child, isSuccess;
4938
+ return __generator(this, function (_b) {
4939
+ switch (_b.label) {
4940
+ case 0:
4941
+ doSkipIfReactAppBuildDirExists = params.doSkipIfReactAppBuildDirExists, buildOptions = params.buildOptions;
4942
+ if (doSkipIfReactAppBuildDirExists &&
4943
+ fs.existsSync(buildOptions.reactAppBuildDirPath)) {
4944
+ return [2 /*return*/, { isAppBuildSuccess: true }];
4945
+ }
4946
+ bundler = buildOptions.bundler;
4947
+ _a = (function () {
4948
+ var e_1, _a;
4949
+ var _b;
4950
+ switch (bundler) {
4951
+ case "vite":
4952
+ return {
4953
+ command: "npx",
4954
+ args: ["vite", "build"],
4955
+ cwd: buildOptions.reactAppRootDirPath
4956
+ };
4957
+ case "webpack": {
4958
+ try {
4959
+ for (var _c = __values([
4960
+ buildOptions.reactAppRootDirPath,
4961
+ buildOptions.npmWorkspaceRootDirPath
4962
+ ]), _d = _c.next(); !_d.done; _d = _c.next()) {
4963
+ var dirPath = _d.value;
4964
+ try {
4965
+ var parsedPackageJson = JSON.parse(fs
4966
+ .readFileSync((0, path_1.join)(dirPath, "package.json"))
4967
+ .toString("utf8"));
4968
+ var _e = __read((_b = Object.entries(parsedPackageJson.scripts).find(function (_a) {
4969
+ var _b = __read(_a, 2), scriptValue = _b[1];
4970
+ (0, assert_1.assert)((0, is_1.is)(scriptValue));
4971
+ if (scriptValue.includes("webpack") &&
4972
+ scriptValue.includes("--mode production")) {
4973
+ return true;
4974
+ }
4975
+ if (scriptValue.includes("react-scripts") &&
4976
+ scriptValue.includes("build")) {
4977
+ return true;
4978
+ }
4979
+ if (scriptValue.includes("react-app-rewired") &&
4980
+ scriptValue.includes("build")) {
4981
+ return true;
4982
+ }
4983
+ if (scriptValue.includes("craco") &&
4984
+ scriptValue.includes("build")) {
4985
+ return true;
4986
+ }
4987
+ })) !== null && _b !== void 0 ? _b : [], 1), scriptName = _e[0];
4988
+ if (scriptName === undefined) {
4989
+ continue;
4990
+ }
4991
+ return {
4992
+ command: "npm",
4993
+ args: ["run", scriptName],
4994
+ cwd: dirPath
4995
+ };
4996
+ }
4997
+ catch (_f) {
4998
+ continue;
4999
+ }
5000
+ }
5001
+ }
5002
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
5003
+ finally {
5004
+ try {
5005
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
5006
+ }
5007
+ finally { if (e_1) throw e_1.error; }
5008
+ }
5009
+ throw new Error("Keycloakify was unable to determine which script is responsible for building the app.");
5010
+ }
5011
+ }
5012
+ })(), command = _a.command, args = _a.args, cwd = _a.cwd;
5013
+ dResult = new Deferred_1.Deferred();
5014
+ child = child_process.spawn(command, args, { cwd: cwd });
5015
+ child.stdout.on("data", function (data) {
5016
+ if (data.toString("utf8").includes("gzip:")) {
5017
+ return;
5018
+ }
5019
+ process.stdout.write(data);
5020
+ });
5021
+ child.stderr.on("data", function (data) { return process.stderr.write(data); });
5022
+ child.on("exit", function (code) { return dResult.resolve({ isSuccess: code === 0 }); });
5023
+ return [4 /*yield*/, dResult.pr];
5024
+ case 1:
5025
+ isSuccess = (_b.sent()).isSuccess;
5026
+ return [2 /*return*/, { isAppBuildSuccess: isSuccess }];
5027
+ }
5028
+ });
5029
+ });
5030
+ }
5031
+ exports.appBuild = appBuild;
5032
+ //# sourceMappingURL=appBuild.js.map
5033
+
5034
+ /***/ }),
5035
+
4835
5036
  /***/ 94229:
4836
5037
  /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
4837
5038
 
@@ -4857,7 +5058,7 @@ __exportStar(__nccwpck_require__(91864), exports);
4857
5058
 
4858
5059
  /***/ }),
4859
5060
 
4860
- /***/ 91864:
5061
+ /***/ 87545:
4861
5062
  /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
4862
5063
 
4863
5064
  "use strict";
@@ -4873,6 +5074,106 @@ var __assign = (this && this.__assign) || function () {
4873
5074
  };
4874
5075
  return __assign.apply(this, arguments);
4875
5076
  };
5077
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5078
+ if (k2 === undefined) k2 = k;
5079
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5080
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
5081
+ desc = { enumerable: true, get: function() { return m[k]; } };
5082
+ }
5083
+ Object.defineProperty(o, k2, desc);
5084
+ }) : (function(o, m, k, k2) {
5085
+ if (k2 === undefined) k2 = k;
5086
+ o[k2] = m[k];
5087
+ }));
5088
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
5089
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
5090
+ }) : function(o, v) {
5091
+ o["default"] = v;
5092
+ });
5093
+ var __importStar = (this && this.__importStar) || function (mod) {
5094
+ if (mod && mod.__esModule) return mod;
5095
+ var result = {};
5096
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
5097
+ __setModuleDefault(result, mod);
5098
+ return result;
5099
+ };
5100
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
5101
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
5102
+ return new (P || (P = Promise))(function (resolve, reject) {
5103
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5104
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
5105
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
5106
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
5107
+ });
5108
+ };
5109
+ var __generator = (this && this.__generator) || function (thisArg, body) {
5110
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
5111
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
5112
+ function verb(n) { return function (v) { return step([n, v]); }; }
5113
+ function step(op) {
5114
+ if (f) throw new TypeError("Generator is already executing.");
5115
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
5116
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
5117
+ if (y = 0, t) op = [op[0] & 2, t.value];
5118
+ switch (op[0]) {
5119
+ case 0: case 1: t = op; break;
5120
+ case 4: _.label++; return { value: op[1], done: false };
5121
+ case 5: _.label++; y = op[1]; op = [0]; continue;
5122
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
5123
+ default:
5124
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
5125
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
5126
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
5127
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
5128
+ if (t[2]) _.ops.pop();
5129
+ _.trys.pop(); continue;
5130
+ }
5131
+ op = body.call(thisArg, _);
5132
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
5133
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
5134
+ }
5135
+ };
5136
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
5137
+ exports.keycloakifyBuild = void 0;
5138
+ var constants_1 = __nccwpck_require__(173);
5139
+ var child_process = __importStar(__nccwpck_require__(32081));
5140
+ var Deferred_1 = __nccwpck_require__(50689);
5141
+ var assert_1 = __nccwpck_require__(88078);
5142
+ (0, assert_1.assert)();
5143
+ function keycloakifyBuild(params) {
5144
+ return __awaiter(this, void 0, void 0, function () {
5145
+ var buildOptions, doSkipBuildJars, dResult, child, isSuccess;
5146
+ var _a;
5147
+ return __generator(this, function (_b) {
5148
+ switch (_b.label) {
5149
+ case 0:
5150
+ buildOptions = params.buildOptions, doSkipBuildJars = params.doSkipBuildJars;
5151
+ dResult = new Deferred_1.Deferred();
5152
+ child = child_process.spawn("npx", ["keycloakify", "build"], {
5153
+ cwd: buildOptions.reactAppRootDirPath,
5154
+ env: __assign(__assign({}, process.env), (doSkipBuildJars ? (_a = {}, _a[constants_1.skipBuildJarsEnvName] = "true", _a) : {}))
5155
+ });
5156
+ child.stdout.on("data", function (data) { return process.stdout.write(data); });
5157
+ child.stderr.on("data", function (data) { return process.stderr.write(data); });
5158
+ child.on("exit", function (code) { return dResult.resolve({ isSuccess: code === 0 }); });
5159
+ return [4 /*yield*/, dResult.pr];
5160
+ case 1:
5161
+ isSuccess = (_b.sent()).isSuccess;
5162
+ return [2 /*return*/, { isKeycloakifyBuildSuccess: isSuccess }];
5163
+ }
5164
+ });
5165
+ });
5166
+ }
5167
+ exports.keycloakifyBuild = keycloakifyBuild;
5168
+ //# sourceMappingURL=keycloakifyBuild.js.map
5169
+
5170
+ /***/ }),
5171
+
5172
+ /***/ 91864:
5173
+ /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
5174
+
5175
+ "use strict";
5176
+
4876
5177
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4877
5178
  if (k2 === undefined) k2 = k;
4878
5179
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -4987,14 +5288,15 @@ var chalk_1 = __importDefault(__nccwpck_require__(78818));
4987
5288
  var chokidar_1 = __importDefault(__nccwpck_require__(42677));
4988
5289
  var waitForDebounce_1 = __nccwpck_require__(18721);
4989
5290
  var getThisCodebaseRootDirPath_1 = __nccwpck_require__(58822);
4990
- var Deferred_1 = __nccwpck_require__(50689);
4991
5291
  var getAbsoluteAndInOsFormatPath_1 = __nccwpck_require__(86644);
4992
5292
  var cli_select_1 = __importDefault(__nccwpck_require__(99398));
4993
5293
  var runExclusive = __importStar(__nccwpck_require__(81708));
4994
5294
  var extractArchive_1 = __nccwpck_require__(29121);
5295
+ var appBuild_1 = __nccwpck_require__(18170);
5296
+ var keycloakifyBuild_1 = __nccwpck_require__(87545);
4995
5297
  function command(params) {
4996
5298
  return __awaiter(this, void 0, void 0, function () {
4997
- var commandOutput, isDockerRunning, cliCommandOptions, buildOptions, metaInfKeycloakThemes, doesImplementAccountTheme, _a, keycloakVersion, keycloakMajorVersionNumber, keycloakVersionRange, jarFileBasename, realmJsonFilePath, jarFilePath, doLinkAccountV1Theme, spawnArgs, child, srcDirPath, handler_1, runBuildKeycloakTheme_1, waitForDebounce_2;
5299
+ var commandOutput, isDockerRunning, cliCommandOptions, buildOptions, isAppBuildSuccess, isKeycloakifyBuildSuccess, metaInfKeycloakThemes, doesImplementAccountTheme, _a, keycloakVersion, keycloakMajorVersionNumber, keycloakVersionRange, jarFileBasename, realmJsonFilePath, jarFilePath, doUseBuiltInAccountV1Theme, accountThemePropertyPatch, spawnArgs, child, srcDirPath, handler_1, runFullBuild_1, waitForDebounce_2;
4998
5300
  var _this = this;
4999
5301
  return __generator(this, function (_b) {
5000
5302
  switch (_b.label) {
@@ -5037,14 +5339,24 @@ function command(params) {
5037
5339
  }
5038
5340
  cliCommandOptions = params.cliCommandOptions;
5039
5341
  buildOptions = (0, buildOptions_1.readBuildOptions)({ cliCommandOptions: cliCommandOptions });
5040
- exit_if_theme_not_built: {
5041
- if (fs.existsSync(buildOptions.keycloakifyBuildDirPath)) {
5042
- break exit_if_theme_not_built;
5043
- }
5044
- console.log([
5045
- "".concat(chalk_1.default.red("The theme has not been built.")),
5046
- "Please run ".concat(chalk_1.default.bold("npx vite && npx keycloakify build"), " first.")
5047
- ].join(" "));
5342
+ return [4 /*yield*/, (0, appBuild_1.appBuild)({
5343
+ doSkipIfReactAppBuildDirExists: true,
5344
+ buildOptions: buildOptions
5345
+ })];
5346
+ case 1:
5347
+ isAppBuildSuccess = (_b.sent()).isAppBuildSuccess;
5348
+ if (!isAppBuildSuccess) {
5349
+ console.log(chalk_1.default.red("App build failed, exiting. Try running 'yarn build-keycloak-theme' and see what's wrong."));
5350
+ process.exit(1);
5351
+ }
5352
+ return [4 /*yield*/, (0, keycloakifyBuild_1.keycloakifyBuild)({
5353
+ doSkipBuildJars: false,
5354
+ buildOptions: buildOptions
5355
+ })];
5356
+ case 2:
5357
+ isKeycloakifyBuildSuccess = (_b.sent()).isKeycloakifyBuildSuccess;
5358
+ if (!isKeycloakifyBuildSuccess) {
5359
+ console.log(chalk_1.default.red("Keycloakify build failed, exiting. Try running 'yarn build-keycloak-theme' and see what's wrong."));
5048
5360
  process.exit(1);
5049
5361
  }
5050
5362
  metaInfKeycloakThemes = (0, metaInfKeycloakThemes_1.readMetaInfKeycloakThemes)({
@@ -5088,7 +5400,7 @@ function command(params) {
5088
5400
  });
5089
5401
  });
5090
5402
  })()];
5091
- case 1:
5403
+ case 3:
5092
5404
  _a = _b.sent(), keycloakVersion = _a.keycloakVersion, keycloakMajorVersionNumber = _a.keycloakMajorNumber;
5093
5405
  keycloakVersionRange = (function () {
5094
5406
  if (doesImplementAccountTheme) {
@@ -5118,12 +5430,6 @@ function command(params) {
5118
5430
  })();
5119
5431
  jarFileBasename = (0, getJarFileBasename_1.getJarFileBasename)({ keycloakVersionRange: keycloakVersionRange }).jarFileBasename;
5120
5432
  console.log("Using Keycloak ".concat(chalk_1.default.bold(jarFileBasename)));
5121
- try {
5122
- child_process.execSync("docker rm --force ".concat(constants_1.containerName), {
5123
- stdio: "ignore"
5124
- });
5125
- }
5126
- catch (_e) { }
5127
5433
  return [4 /*yield*/, (function () { return __awaiter(_this, void 0, void 0, function () {
5128
5434
  var dirPath, filePath, value;
5129
5435
  return __generator(this, function (_a) {
@@ -5161,61 +5467,100 @@ function command(params) {
5161
5467
  }
5162
5468
  });
5163
5469
  }); })()];
5164
- case 2:
5470
+ case 4:
5165
5471
  realmJsonFilePath = _b.sent();
5166
5472
  jarFilePath = (0, path_1.join)(buildOptions.keycloakifyBuildDirPath, jarFileBasename);
5167
- doLinkAccountV1Theme = false;
5168
- return [4 /*yield*/, (0, extractArchive_1.extractArchive)({
5169
- archiveFilePath: jarFilePath,
5170
- onArchiveFile: function (_a) { return __awaiter(_this, [_a], void 0, function (_b) {
5171
- var _c, _d, themeName, e_1_1;
5172
- var e_1, _e;
5173
- var relativeFilePathInArchive = _b.relativeFilePathInArchive, readFile = _b.readFile, writeFile = _b.writeFile;
5174
- return __generator(this, function (_f) {
5175
- switch (_f.label) {
5176
- case 0:
5177
- _f.trys.push([0, 6, 7, 8]);
5178
- _c = __values(buildOptions.themeNames), _d = _c.next();
5179
- _f.label = 1;
5180
- case 1:
5181
- if (!!_d.done) return [3 /*break*/, 5];
5182
- themeName = _d.value;
5183
- if (!(relativeFilePathInArchive ===
5184
- (0, path_1.join)("theme", themeName, "account", "theme.properties"))) return [3 /*break*/, 4];
5185
- return [4 /*yield*/, readFile()];
5186
- case 2:
5187
- if ((_f.sent())
5188
- .toString("utf8")
5189
- .includes("parent=".concat(constants_1.accountV1ThemeName))) {
5190
- doLinkAccountV1Theme = true;
5191
- }
5192
- return [4 /*yield*/, writeFile({
5193
- filePath: (0, path_1.join)(buildOptions.keycloakifyBuildDirPath, "src", "main", "resources", "theme", themeName, "account", "theme.properties")
5194
- })];
5195
- case 3:
5196
- _f.sent();
5197
- _f.label = 4;
5198
- case 4:
5199
- _d = _c.next();
5200
- return [3 /*break*/, 1];
5201
- case 5: return [3 /*break*/, 8];
5202
- case 6:
5203
- e_1_1 = _f.sent();
5204
- e_1 = { error: e_1_1 };
5205
- return [3 /*break*/, 8];
5206
- case 7:
5207
- try {
5208
- if (_d && !_d.done && (_e = _c.return)) _e.call(_c);
5209
- }
5210
- finally { if (e_1) throw e_1.error; }
5211
- return [7 /*endfinally*/];
5212
- case 8: return [2 /*return*/];
5213
- }
5214
- });
5215
- }); }
5216
- })];
5217
- case 3:
5218
- _b.sent();
5473
+ return [4 /*yield*/, (function () { return __awaiter(_this, void 0, void 0, function () {
5474
+ var doUseBuiltInAccountV1Theme;
5475
+ var _this = this;
5476
+ return __generator(this, function (_a) {
5477
+ switch (_a.label) {
5478
+ case 0:
5479
+ doUseBuiltInAccountV1Theme = false;
5480
+ return [4 /*yield*/, (0, extractArchive_1.extractArchive)({
5481
+ archiveFilePath: jarFilePath,
5482
+ onArchiveFile: function (_a) { return __awaiter(_this, [_a], void 0, function (_b) {
5483
+ var _c, _d, themeName, e_1_1;
5484
+ var e_1, _e;
5485
+ var relativeFilePathInArchive = _b.relativeFilePathInArchive, readFile = _b.readFile, earlyExit = _b.earlyExit;
5486
+ return __generator(this, function (_f) {
5487
+ switch (_f.label) {
5488
+ case 0:
5489
+ _f.trys.push([0, 5, 6, 7]);
5490
+ _c = __values(buildOptions.themeNames), _d = _c.next();
5491
+ _f.label = 1;
5492
+ case 1:
5493
+ if (!!_d.done) return [3 /*break*/, 4];
5494
+ themeName = _d.value;
5495
+ if (!(relativeFilePathInArchive ===
5496
+ (0, path_1.join)("theme", themeName, "account", "theme.properties"))) return [3 /*break*/, 3];
5497
+ return [4 /*yield*/, readFile()];
5498
+ case 2:
5499
+ if ((_f.sent())
5500
+ .toString("utf8")
5501
+ .includes("parent=keycloak")) {
5502
+ doUseBuiltInAccountV1Theme = true;
5503
+ }
5504
+ earlyExit();
5505
+ _f.label = 3;
5506
+ case 3:
5507
+ _d = _c.next();
5508
+ return [3 /*break*/, 1];
5509
+ case 4: return [3 /*break*/, 7];
5510
+ case 5:
5511
+ e_1_1 = _f.sent();
5512
+ e_1 = { error: e_1_1 };
5513
+ return [3 /*break*/, 7];
5514
+ case 6:
5515
+ try {
5516
+ if (_d && !_d.done && (_e = _c.return)) _e.call(_c);
5517
+ }
5518
+ finally { if (e_1) throw e_1.error; }
5519
+ return [7 /*endfinally*/];
5520
+ case 7: return [2 /*return*/];
5521
+ }
5522
+ });
5523
+ }); }
5524
+ })];
5525
+ case 1:
5526
+ _a.sent();
5527
+ return [2 /*return*/, { doUseBuiltInAccountV1Theme: doUseBuiltInAccountV1Theme }];
5528
+ }
5529
+ });
5530
+ }); })()];
5531
+ case 5:
5532
+ doUseBuiltInAccountV1Theme = (_b.sent()).doUseBuiltInAccountV1Theme;
5533
+ accountThemePropertyPatch = !doUseBuiltInAccountV1Theme
5534
+ ? undefined
5535
+ : function () {
5536
+ var e_2, _a;
5537
+ try {
5538
+ for (var _b = __values(buildOptions.themeNames), _c = _b.next(); !_c.done; _c = _b.next()) {
5539
+ var themeName = _c.value;
5540
+ var filePath = (0, path_1.join)(buildOptions.keycloakifyBuildDirPath, "src", "main", "resources", "theme", themeName, "account", "theme.properties");
5541
+ var sourceCode = fs.readFileSync(filePath);
5542
+ var modifiedSourceCode = Buffer.from(sourceCode
5543
+ .toString("utf8")
5544
+ .replace("parent=".concat(constants_1.accountV1ThemeName), "parent=keycloak"), "utf8");
5545
+ (0, assert_1.assert)(Buffer.compare(modifiedSourceCode, sourceCode) !== 0);
5546
+ fs.writeFileSync(filePath, modifiedSourceCode);
5547
+ }
5548
+ }
5549
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
5550
+ finally {
5551
+ try {
5552
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
5553
+ }
5554
+ finally { if (e_2) throw e_2.error; }
5555
+ }
5556
+ };
5557
+ accountThemePropertyPatch === null || accountThemePropertyPatch === void 0 ? void 0 : accountThemePropertyPatch();
5558
+ try {
5559
+ child_process.execSync("docker rm --force ".concat(constants_1.containerName), {
5560
+ stdio: "ignore"
5561
+ });
5562
+ }
5563
+ catch (_e) { }
5219
5564
  spawnArgs = [
5220
5565
  "docker",
5221
5566
  __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([
@@ -5227,7 +5572,7 @@ function command(params) {
5227
5572
  "".concat(realmJsonFilePath, ":/opt/keycloak/data/import/myrealm-realm.json")
5228
5573
  ])), false), ["-v", "".concat(jarFilePath, ":/opt/keycloak/providers/keycloak-theme.jar")], false), __read((keycloakMajorVersionNumber <= 20
5229
5574
  ? ["-e", "JAVA_OPTS=-Dkeycloak.profile=preview"]
5230
- : [])), false), __read(__spreadArray(__spreadArray([], __read(buildOptions.themeNames), false), __read((doLinkAccountV1Theme ? [constants_1.accountV1ThemeName] : [])), false).map(function (themeName) { return ({
5575
+ : [])), false), __read(__spreadArray(__spreadArray([], __read(buildOptions.themeNames), false), __read((doUseBuiltInAccountV1Theme ? [] : [constants_1.accountV1ThemeName])), false).map(function (themeName) { return ({
5231
5576
  localDirPath: (0, path_1.join)(buildOptions.keycloakifyBuildDirPath, "src", "main", "resources", "theme", themeName),
5232
5577
  containerDirPath: "/opt/keycloak/themes/".concat(themeName)
5233
5578
  }); })
@@ -5266,18 +5611,19 @@ function command(params) {
5266
5611
  case 1:
5267
5612
  _a.sent();
5268
5613
  console.log([
5614
+ "",
5615
+ "Keycloak Admin console: ".concat(chalk_1.default.cyan.bold("http://localhost:".concat(cliCommandOptions.port))),
5616
+ "- user: ".concat(chalk_1.default.cyan.bold("admin")),
5617
+ "- password: ".concat(chalk_1.default.cyan.bold("admin")),
5618
+ "",
5269
5619
  "",
5270
5620
  "".concat(chalk_1.default.green("Your theme is accessible at:")),
5271
- "".concat(chalk_1.default.green("➜"), " ").concat(chalk_1.default.cyan.bold("https://my-theme.keycloakify.dev/")),
5621
+ "".concat(chalk_1.default.green("➜"), " ").concat(chalk_1.default.cyan.bold("https://my-theme.keycloakify.dev".concat(cliCommandOptions.port === 8080 ? "" : "?port=".concat(cliCommandOptions.port)))),
5272
5622
  "",
5273
5623
  "You can login with the following credentials:",
5274
5624
  "- username: ".concat(chalk_1.default.cyan.bold("testuser")),
5275
5625
  "- password: ".concat(chalk_1.default.cyan.bold("password123")),
5276
5626
  "",
5277
- "Keycloak Admin console: ".concat(chalk_1.default.cyan.bold("http://localhost:".concat(cliCommandOptions.port))),
5278
- "- user: ".concat(chalk_1.default.cyan.bold("admin")),
5279
- "- password: ".concat(chalk_1.default.cyan.bold("admin")),
5280
- "",
5281
5627
  "Watching for changes in ".concat(chalk_1.default.bold(".".concat(path_1.sep).concat((0, path_1.relative)(process.cwd(), srcDirPath))))
5282
5628
  ].join("\n"));
5283
5629
  return [2 /*return*/];
@@ -5287,52 +5633,32 @@ function command(params) {
5287
5633
  child.stdout.on("data", handler_1);
5288
5634
  }
5289
5635
  {
5290
- runBuildKeycloakTheme_1 = runExclusive.build(function () { return __awaiter(_this, void 0, void 0, function () {
5291
- var dResult_1, child_1, isSuccess, dResult_2, child_2, isSuccess;
5292
- var _a;
5293
- return __generator(this, function (_b) {
5294
- switch (_b.label) {
5636
+ runFullBuild_1 = runExclusive.build(function () { return __awaiter(_this, void 0, void 0, function () {
5637
+ var isAppBuildSuccess, isKeycloakifyBuildSuccess;
5638
+ return __generator(this, function (_a) {
5639
+ switch (_a.label) {
5295
5640
  case 0:
5296
5641
  console.log(chalk_1.default.cyan("Detected changes in the theme. Rebuilding ..."));
5297
- dResult_1 = new Deferred_1.Deferred();
5298
- child_1 = child_process.spawn("npx", ["vite", "build"], {
5299
- cwd: buildOptions.reactAppRootDirPath
5300
- });
5301
- child_1.stdout.on("data", function (data) {
5302
- if (data.toString("utf8").includes("gzip:")) {
5303
- return;
5304
- }
5305
- process.stdout.write(data);
5306
- });
5307
- child_1.stderr.on("data", function (data) { return process.stderr.write(data); });
5308
- child_1.on("exit", function (code) { return dResult_1.resolve({ isSuccess: code === 0 }); });
5309
- return [4 /*yield*/, dResult_1.pr];
5642
+ return [4 /*yield*/, (0, appBuild_1.appBuild)({
5643
+ doSkipIfReactAppBuildDirExists: false,
5644
+ buildOptions: buildOptions
5645
+ })];
5310
5646
  case 1:
5311
- isSuccess = (_b.sent()).isSuccess;
5312
- if (!isSuccess) {
5647
+ isAppBuildSuccess = (_a.sent()).isAppBuildSuccess;
5648
+ if (!isAppBuildSuccess) {
5313
5649
  return [2 /*return*/];
5314
5650
  }
5315
- dResult_2 = new Deferred_1.Deferred();
5316
- child_2 = child_process.spawn("npx", ["keycloakify", "build"], {
5317
- cwd: buildOptions.reactAppRootDirPath,
5318
- env: __assign(__assign({}, process.env), (_a = {}, _a[constants_1.skipBuildJarsEnvName] = "true", _a))
5319
- });
5320
- child_2.stdout.on("data", function (data) { return process.stdout.write(data); });
5321
- child_2.stderr.on("data", function (data) { return process.stderr.write(data); });
5322
- child_2.on("exit", function (code) {
5323
- if (code !== 0) {
5324
- console.log(chalk_1.default.yellow("Theme not updated, build failed"));
5325
- return;
5326
- }
5327
- console.log(chalk_1.default.green("Rebuild done"));
5328
- });
5329
- child_2.on("exit", function (code) { return dResult_2.resolve({ isSuccess: code === 0 }); });
5330
- return [4 /*yield*/, dResult_2.pr];
5651
+ return [4 /*yield*/, (0, keycloakifyBuild_1.keycloakifyBuild)({
5652
+ doSkipBuildJars: true,
5653
+ buildOptions: buildOptions
5654
+ })];
5331
5655
  case 2:
5332
- isSuccess = (_b.sent()).isSuccess;
5333
- if (!isSuccess) {
5656
+ isKeycloakifyBuildSuccess = (_a.sent()).isKeycloakifyBuildSuccess;
5657
+ if (!isKeycloakifyBuildSuccess) {
5334
5658
  return [2 /*return*/];
5335
5659
  }
5660
+ accountThemePropertyPatch === null || accountThemePropertyPatch === void 0 ? void 0 : accountThemePropertyPatch();
5661
+ console.log(chalk_1.default.green("Theme rebuilt and updated in Keycloak."));
5336
5662
  return [2 /*return*/];
5337
5663
  }
5338
5664
  });
@@ -5348,7 +5674,7 @@ function command(params) {
5348
5674
  case 0: return [4 /*yield*/, waitForDebounce_2()];
5349
5675
  case 1:
5350
5676
  _a.sent();
5351
- runBuildKeycloakTheme_1();
5677
+ runFullBuild_1();
5352
5678
  return [2 /*return*/];
5353
5679
  }
5354
5680
  });
@@ -6366,6 +6692,7 @@ function extractArchive(params) {
6366
6692
  });
6367
6693
  };
6368
6694
  zipFile.on("entry", function (entry) { return __awaiter(_this, void 0, void 0, function () {
6695
+ var hasEarlyExitBeenCalled_1;
6369
6696
  return __generator(this, function (_a) {
6370
6697
  switch (_a.label) {
6371
6698
  case 0:
@@ -6373,13 +6700,22 @@ function extractArchive(params) {
6373
6700
  if (entry.fileName.endsWith(path_1.sep)) {
6374
6701
  return [3 /*break*/, 2];
6375
6702
  }
6703
+ hasEarlyExitBeenCalled_1 = false;
6376
6704
  return [4 /*yield*/, onArchiveFile({
6377
6705
  relativeFilePathInArchive: entry.fileName.split("/").join(path_1.sep),
6378
6706
  readFile: function () { return readFile(entry); },
6379
- writeFile: function (params) { return writeFile(entry, params); }
6707
+ writeFile: function (params) { return writeFile(entry, params); },
6708
+ earlyExit: function () {
6709
+ hasEarlyExitBeenCalled_1 = true;
6710
+ }
6380
6711
  })];
6381
6712
  case 1:
6382
6713
  _a.sent();
6714
+ if (hasEarlyExitBeenCalled_1) {
6715
+ zipFile.close();
6716
+ dDone.resolve();
6717
+ return [2 /*return*/];
6718
+ }
6383
6719
  _a.label = 2;
6384
6720
  case 2:
6385
6721
  zipFile.readEntry();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keycloakify",
3
- "version": "10.0.0-rc.18",
3
+ "version": "10.0.0-rc.19",
4
4
  "description": "Create Keycloak themes using React",
5
5
  "repository": {
6
6
  "type": "git",
@@ -509,7 +509,9 @@
509
509
  "src/bin/shared/getThemeSrcDirPath.ts",
510
510
  "src/bin/shared/metaInfKeycloakThemes.ts",
511
511
  "src/bin/shared/promptKeycloakVersion.ts",
512
+ "src/bin/start-keycloak/appBuild.ts",
512
513
  "src/bin/start-keycloak/index.ts",
514
+ "src/bin/start-keycloak/keycloakifyBuild.ts",
513
515
  "src/bin/start-keycloak/myrealm-realm-23.json",
514
516
  "src/bin/start-keycloak/myrealm-realm-24.json",
515
517
  "src/bin/start-keycloak/start-keycloak.ts",
@@ -2,8 +2,6 @@
2
2
  (()=>{
3
3
  <#assign pageId="PAGE_ID_xIgLsPgGId9D8e">
4
4
  const out = ${ftl_object_to_js_code_declaring_an_object(.data_model, [])?no_esc};
5
- out["msg"]= function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); };
6
- out["advancedMsg"]= function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); };
7
5
  out["messagesPerField"]= {
8
6
  <#assign fieldNames = [ FIELD_NAMES_eKsIY4ZsZ4xeM ]>
9
7
  <#attempt>
@@ -181,6 +179,26 @@ try {
181
179
  out["url"]["resourcesCommonPath"] = out["url"]["resourcesPath"] + "/" + "RESOURCES_COMMON_cLsLsMrtDkpVv";
182
180
  } catch(error) { }
183
181
 
182
+ <#if profile?? && profile.attributes??>
183
+ out["__localizationReamlOverrides_userProfile"] = {
184
+ <#list profile.attributes as attribute>
185
+ <#if attribute.annotations?? && attribute.displayName??>
186
+ "${attribute.displayName}xx": "${advancedMsg(attribute.displayName)?no_esc}",
187
+ </#if>
188
+ <#if attribute.annotations.inputHelperTextBefore??>
189
+ "${attribute.annotations.inputHelperTextBefore}": "${advancedMsg(attribute.annotations.inputHelperTextBefore)?no_esc}",
190
+ </#if>
191
+ <#if attribute.annotations.inputHelperTextAfter??>
192
+ "${attribute.annotations.inputHelperTextAfter}": "${advancedMsg(attribute.annotations.inputHelperTextAfter)?no_esc}",
193
+ </#if>
194
+ <#if attribute.annotations.inputTypePlaceholder??>
195
+ "${attribute.annotations.inputTypePlaceholder}": "${advancedMsg(attribute.annotations.inputTypePlaceholder)?no_esc}",
196
+ </#if>
197
+ </#list>
198
+ };
199
+ </#if>
200
+
201
+
184
202
  return out;
185
203
 
186
204
  })();
@@ -0,0 +1,128 @@
1
+ import * as child_process from "child_process";
2
+ import { Deferred } from "evt/tools/Deferred";
3
+ import { assert } from "tsafe/assert";
4
+ import { is } from "tsafe/is";
5
+ import type { BuildOptions } from "../shared/buildOptions";
6
+ import * as fs from "fs";
7
+ import { join as pathJoin } from "path";
8
+
9
+ export type BuildOptionsLike = {
10
+ reactAppRootDirPath: string;
11
+ keycloakifyBuildDirPath: string;
12
+ bundler: "vite" | "webpack";
13
+ npmWorkspaceRootDirPath: string;
14
+ reactAppBuildDirPath: string;
15
+ };
16
+
17
+ assert<BuildOptions extends BuildOptionsLike ? true : false>();
18
+
19
+ export async function appBuild(params: {
20
+ doSkipIfReactAppBuildDirExists: boolean;
21
+ buildOptions: BuildOptionsLike;
22
+ }): Promise<{ isAppBuildSuccess: boolean }> {
23
+ const { doSkipIfReactAppBuildDirExists, buildOptions } = params;
24
+
25
+ if (
26
+ doSkipIfReactAppBuildDirExists &&
27
+ fs.existsSync(buildOptions.reactAppBuildDirPath)
28
+ ) {
29
+ return { isAppBuildSuccess: true };
30
+ }
31
+
32
+ const { bundler } = buildOptions;
33
+
34
+ const { command, args, cwd } = (() => {
35
+ switch (bundler) {
36
+ case "vite":
37
+ return {
38
+ command: "npx",
39
+ args: ["vite", "build"],
40
+ cwd: buildOptions.reactAppRootDirPath
41
+ };
42
+ case "webpack": {
43
+ for (const dirPath of [
44
+ buildOptions.reactAppRootDirPath,
45
+ buildOptions.npmWorkspaceRootDirPath
46
+ ]) {
47
+ try {
48
+ const parsedPackageJson = JSON.parse(
49
+ fs
50
+ .readFileSync(pathJoin(dirPath, "package.json"))
51
+ .toString("utf8")
52
+ );
53
+
54
+ const [scriptName] =
55
+ Object.entries(parsedPackageJson.scripts).find(
56
+ ([, scriptValue]) => {
57
+ assert(is<string>(scriptValue));
58
+ if (
59
+ scriptValue.includes("webpack") &&
60
+ scriptValue.includes("--mode production")
61
+ ) {
62
+ return true;
63
+ }
64
+
65
+ if (
66
+ scriptValue.includes("react-scripts") &&
67
+ scriptValue.includes("build")
68
+ ) {
69
+ return true;
70
+ }
71
+
72
+ if (
73
+ scriptValue.includes("react-app-rewired") &&
74
+ scriptValue.includes("build")
75
+ ) {
76
+ return true;
77
+ }
78
+
79
+ if (
80
+ scriptValue.includes("craco") &&
81
+ scriptValue.includes("build")
82
+ ) {
83
+ return true;
84
+ }
85
+ }
86
+ ) ?? [];
87
+
88
+ if (scriptName === undefined) {
89
+ continue;
90
+ }
91
+
92
+ return {
93
+ command: "npm",
94
+ args: ["run", scriptName],
95
+ cwd: dirPath
96
+ };
97
+ } catch {
98
+ continue;
99
+ }
100
+ }
101
+
102
+ throw new Error(
103
+ "Keycloakify was unable to determine which script is responsible for building the app."
104
+ );
105
+ }
106
+ }
107
+ })();
108
+
109
+ const dResult = new Deferred<{ isSuccess: boolean }>();
110
+
111
+ const child = child_process.spawn(command, args, { cwd });
112
+
113
+ child.stdout.on("data", data => {
114
+ if (data.toString("utf8").includes("gzip:")) {
115
+ return;
116
+ }
117
+
118
+ process.stdout.write(data);
119
+ });
120
+
121
+ child.stderr.on("data", data => process.stderr.write(data));
122
+
123
+ child.on("exit", code => dResult.resolve({ isSuccess: code === 0 }));
124
+
125
+ const { isSuccess } = await dResult.pr;
126
+
127
+ return { isAppBuildSuccess: isSuccess };
128
+ }
@@ -0,0 +1,41 @@
1
+ import { skipBuildJarsEnvName } from "../shared/constants";
2
+ import * as child_process from "child_process";
3
+ import { Deferred } from "evt/tools/Deferred";
4
+ import { assert } from "tsafe/assert";
5
+ import type { BuildOptions } from "../shared/buildOptions";
6
+
7
+ export type BuildOptionsLike = {
8
+ reactAppRootDirPath: string;
9
+ keycloakifyBuildDirPath: string;
10
+ bundler: "vite" | "webpack";
11
+ npmWorkspaceRootDirPath: string;
12
+ };
13
+
14
+ assert<BuildOptions extends BuildOptionsLike ? true : false>();
15
+
16
+ export async function keycloakifyBuild(params: {
17
+ doSkipBuildJars: boolean;
18
+ buildOptions: BuildOptionsLike;
19
+ }): Promise<{ isKeycloakifyBuildSuccess: boolean }> {
20
+ const { buildOptions, doSkipBuildJars } = params;
21
+
22
+ const dResult = new Deferred<{ isSuccess: boolean }>();
23
+
24
+ const child = child_process.spawn("npx", ["keycloakify", "build"], {
25
+ cwd: buildOptions.reactAppRootDirPath,
26
+ env: {
27
+ ...process.env,
28
+ ...(doSkipBuildJars ? { [skipBuildJarsEnvName]: "true" } : {})
29
+ }
30
+ });
31
+
32
+ child.stdout.on("data", data => process.stdout.write(data));
33
+
34
+ child.stderr.on("data", data => process.stderr.write(data));
35
+
36
+ child.on("exit", code => dResult.resolve({ isSuccess: code === 0 }));
37
+
38
+ const { isSuccess } = await dResult.pr;
39
+
40
+ return { isKeycloakifyBuildSuccess: isSuccess };
41
+ }
@@ -2,11 +2,7 @@ import { readBuildOptions } from "../shared/buildOptions";
2
2
  import type { CliCommandOptions as CliCommandOptions_common } from "../main";
3
3
  import { promptKeycloakVersion } from "../shared/promptKeycloakVersion";
4
4
  import { readMetaInfKeycloakThemes } from "../shared/metaInfKeycloakThemes";
5
- import {
6
- accountV1ThemeName,
7
- skipBuildJarsEnvName,
8
- containerName
9
- } from "../shared/constants";
5
+ import { accountV1ThemeName, containerName } from "../shared/constants";
10
6
  import { SemVer } from "../tools/SemVer";
11
7
  import type { KeycloakVersionRange } from "../shared/KeycloakVersionRange";
12
8
  import { getJarFileBasename } from "../shared/getJarFileBasename";
@@ -18,11 +14,12 @@ import chalk from "chalk";
18
14
  import chokidar from "chokidar";
19
15
  import { waitForDebounceFactory } from "powerhooks/tools/waitForDebounce";
20
16
  import { getThisCodebaseRootDirPath } from "../tools/getThisCodebaseRootDirPath";
21
- import { Deferred } from "evt/tools/Deferred";
22
17
  import { getAbsoluteAndInOsFormatPath } from "../tools/getAbsoluteAndInOsFormatPath";
23
18
  import cliSelect from "cli-select";
24
19
  import * as runExclusive from "run-exclusive";
25
20
  import { extractArchive } from "../tools/extractArchive";
21
+ import { appBuild } from "./appBuild";
22
+ import { keycloakifyBuild } from "./keycloakifyBuild";
26
23
 
27
24
  export type CliCommandOptions = CliCommandOptions_common & {
28
25
  port: number;
@@ -85,18 +82,34 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
85
82
 
86
83
  const buildOptions = readBuildOptions({ cliCommandOptions });
87
84
 
88
- exit_if_theme_not_built: {
89
- if (fs.existsSync(buildOptions.keycloakifyBuildDirPath)) {
90
- break exit_if_theme_not_built;
85
+ {
86
+ const { isAppBuildSuccess } = await appBuild({
87
+ doSkipIfReactAppBuildDirExists: true,
88
+ buildOptions
89
+ });
90
+
91
+ if (!isAppBuildSuccess) {
92
+ console.log(
93
+ chalk.red(
94
+ `App build failed, exiting. Try running 'yarn build-keycloak-theme' and see what's wrong.`
95
+ )
96
+ );
97
+ process.exit(1);
91
98
  }
92
99
 
93
- console.log(
94
- [
95
- `${chalk.red("The theme has not been built.")}`,
96
- `Please run ${chalk.bold("npx vite && npx keycloakify build")} first.`
97
- ].join(" ")
98
- );
99
- process.exit(1);
100
+ const { isKeycloakifyBuildSuccess } = await keycloakifyBuild({
101
+ doSkipBuildJars: false,
102
+ buildOptions
103
+ });
104
+
105
+ if (!isKeycloakifyBuildSuccess) {
106
+ console.log(
107
+ chalk.red(
108
+ `Keycloakify build failed, exiting. Try running 'yarn build-keycloak-theme' and see what's wrong.`
109
+ )
110
+ );
111
+ process.exit(1);
112
+ }
100
113
  }
101
114
 
102
115
  const metaInfKeycloakThemes = readMetaInfKeycloakThemes({
@@ -191,12 +204,6 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
191
204
 
192
205
  console.log(`Using Keycloak ${chalk.bold(jarFileBasename)}`);
193
206
 
194
- try {
195
- child_process.execSync(`docker rm --force ${containerName}`, {
196
- stdio: "ignore"
197
- });
198
- } catch {}
199
-
200
207
  const realmJsonFilePath = await (async () => {
201
208
  if (cliCommandOptions.realmJsonFilePath !== undefined) {
202
209
  console.log(
@@ -255,40 +262,71 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
255
262
 
256
263
  const jarFilePath = pathJoin(buildOptions.keycloakifyBuildDirPath, jarFileBasename);
257
264
 
258
- let doLinkAccountV1Theme = false;
265
+ const { doUseBuiltInAccountV1Theme } = await (async () => {
266
+ let doUseBuiltInAccountV1Theme = false;
259
267
 
260
- await extractArchive({
261
- archiveFilePath: jarFilePath,
262
- onArchiveFile: async ({ relativeFilePathInArchive, readFile, writeFile }) => {
263
- for (const themeName of buildOptions.themeNames) {
264
- if (
265
- relativeFilePathInArchive ===
266
- pathJoin("theme", themeName, "account", "theme.properties")
267
- ) {
268
+ await extractArchive({
269
+ archiveFilePath: jarFilePath,
270
+ onArchiveFile: async ({ relativeFilePathInArchive, readFile, earlyExit }) => {
271
+ for (const themeName of buildOptions.themeNames) {
268
272
  if (
269
- (await readFile())
270
- .toString("utf8")
271
- .includes(`parent=${accountV1ThemeName}`)
273
+ relativeFilePathInArchive ===
274
+ pathJoin("theme", themeName, "account", "theme.properties")
272
275
  ) {
273
- doLinkAccountV1Theme = true;
276
+ if (
277
+ (await readFile())
278
+ .toString("utf8")
279
+ .includes("parent=keycloak")
280
+ ) {
281
+ doUseBuiltInAccountV1Theme = true;
282
+ }
283
+
284
+ earlyExit();
274
285
  }
275
-
276
- await writeFile({
277
- filePath: pathJoin(
278
- buildOptions.keycloakifyBuildDirPath,
279
- "src",
280
- "main",
281
- "resources",
282
- "theme",
283
- themeName,
284
- "account",
285
- "theme.properties"
286
- )
287
- });
288
286
  }
289
287
  }
290
- }
291
- });
288
+ });
289
+
290
+ return { doUseBuiltInAccountV1Theme };
291
+ })();
292
+
293
+ const accountThemePropertyPatch = !doUseBuiltInAccountV1Theme
294
+ ? undefined
295
+ : () => {
296
+ for (const themeName of buildOptions.themeNames) {
297
+ const filePath = pathJoin(
298
+ buildOptions.keycloakifyBuildDirPath,
299
+ "src",
300
+ "main",
301
+ "resources",
302
+ "theme",
303
+ themeName,
304
+ "account",
305
+ "theme.properties"
306
+ );
307
+
308
+ const sourceCode = fs.readFileSync(filePath);
309
+
310
+ const modifiedSourceCode = Buffer.from(
311
+ sourceCode
312
+ .toString("utf8")
313
+ .replace(`parent=${accountV1ThemeName}`, "parent=keycloak"),
314
+ "utf8"
315
+ );
316
+
317
+ assert(Buffer.compare(modifiedSourceCode, sourceCode) !== 0);
318
+
319
+ fs.writeFileSync(filePath, modifiedSourceCode);
320
+ }
321
+ };
322
+
323
+ accountThemePropertyPatch?.();
324
+
325
+ try {
326
+ child_process.execSync(`docker rm --force ${containerName}`, {
327
+ stdio: "ignore"
328
+ });
329
+ } catch {}
292
330
 
293
331
  const spawnArgs = [
294
332
  "docker",
@@ -310,7 +348,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
310
348
  : []),
311
349
  ...[
312
350
  ...buildOptions.themeNames,
313
- ...(doLinkAccountV1Theme ? [accountV1ThemeName] : [])
351
+ ...(doUseBuiltInAccountV1Theme ? [] : [accountV1ThemeName])
314
352
  ]
315
353
  .map(themeName => ({
316
354
  localDirPath: pathJoin(
@@ -362,22 +400,23 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
362
400
 
363
401
  console.log(
364
402
  [
403
+ "",
404
+ `Keycloak Admin console: ${chalk.cyan.bold(
405
+ `http://localhost:${cliCommandOptions.port}`
406
+ )}`,
407
+ `- user: ${chalk.cyan.bold("admin")}`,
408
+ `- password: ${chalk.cyan.bold("admin")}`,
409
+ "",
365
410
  "",
366
411
  `${chalk.green("Your theme is accessible at:")}`,
367
412
  `${chalk.green("➜")} ${chalk.cyan.bold(
368
- "https://my-theme.keycloakify.dev/"
413
+ `https://my-theme.keycloakify.dev${cliCommandOptions.port === 8080 ? "" : `?port=${cliCommandOptions.port}`}`
369
414
  )}`,
370
415
  "",
371
416
  "You can login with the following credentials:",
372
417
  `- username: ${chalk.cyan.bold("testuser")}`,
373
418
  `- password: ${chalk.cyan.bold("password123")}`,
374
419
  "",
375
- `Keycloak Admin console: ${chalk.cyan.bold(
376
- `http://localhost:${cliCommandOptions.port}`
377
- )}`,
378
- `- user: ${chalk.cyan.bold("admin")}`,
379
- `- password: ${chalk.cyan.bold("admin")}`,
380
- "",
381
420
  `Watching for changes in ${chalk.bold(
382
421
  `.${pathSep}${pathRelative(process.cwd(), srcDirPath)}`
383
422
  )}`
@@ -389,67 +428,30 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
389
428
  }
390
429
 
391
430
  {
392
- const runBuildKeycloakTheme = runExclusive.build(async () => {
431
+ const runFullBuild = runExclusive.build(async () => {
393
432
  console.log(chalk.cyan("Detected changes in the theme. Rebuilding ..."));
394
433
 
395
- {
396
- const dResult = new Deferred<{ isSuccess: boolean }>();
397
-
398
- const child = child_process.spawn("npx", ["vite", "build"], {
399
- cwd: buildOptions.reactAppRootDirPath
400
- });
401
-
402
- child.stdout.on("data", data => {
403
- if (data.toString("utf8").includes("gzip:")) {
404
- return;
405
- }
406
-
407
- process.stdout.write(data);
408
- });
409
-
410
- child.stderr.on("data", data => process.stderr.write(data));
411
-
412
- child.on("exit", code => dResult.resolve({ isSuccess: code === 0 }));
413
-
414
- const { isSuccess } = await dResult.pr;
434
+ const { isAppBuildSuccess } = await appBuild({
435
+ doSkipIfReactAppBuildDirExists: false,
436
+ buildOptions
437
+ });
415
438
 
416
- if (!isSuccess) {
417
- return;
418
- }
439
+ if (!isAppBuildSuccess) {
440
+ return;
419
441
  }
420
442
 
421
- {
422
- const dResult = new Deferred<{ isSuccess: boolean }>();
423
-
424
- const child = child_process.spawn("npx", ["keycloakify", "build"], {
425
- cwd: buildOptions.reactAppRootDirPath,
426
- env: {
427
- ...process.env,
428
- [skipBuildJarsEnvName]: "true"
429
- }
430
- });
431
-
432
- child.stdout.on("data", data => process.stdout.write(data));
433
-
434
- child.stderr.on("data", data => process.stderr.write(data));
435
-
436
- child.on("exit", code => {
437
- if (code !== 0) {
438
- console.log(chalk.yellow("Theme not updated, build failed"));
439
- return;
440
- }
441
-
442
- console.log(chalk.green("Rebuild done"));
443
- });
443
+ const { isKeycloakifyBuildSuccess } = await keycloakifyBuild({
444
+ doSkipBuildJars: true,
445
+ buildOptions
446
+ });
444
447
 
445
- child.on("exit", code => dResult.resolve({ isSuccess: code === 0 }));
448
+ if (!isKeycloakifyBuildSuccess) {
449
+ return;
450
+ }
446
451
 
447
- const { isSuccess } = await dResult.pr;
452
+ accountThemePropertyPatch?.();
448
453
 
449
- if (!isSuccess) {
450
- return;
451
- }
452
- }
454
+ console.log(chalk.green("Theme rebuilt and updated in Keycloak."));
453
455
  });
454
456
 
455
457
  const { waitForDebounce } = waitForDebounceFactory({ delay: 400 });
@@ -461,7 +463,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
461
463
  .on("all", async () => {
462
464
  await waitForDebounce();
463
465
 
464
- runBuildKeycloakTheme();
466
+ runFullBuild();
465
467
  });
466
468
  }
467
469
  }
@@ -11,6 +11,7 @@ export async function extractArchive(params: {
11
11
  relativeFilePathInArchive: string;
12
12
  readFile: () => Promise<Buffer>;
13
13
  writeFile: (params: { filePath: string; modifiedData?: Buffer }) => Promise<void>;
14
+ earlyExit: () => void;
14
15
  }) => Promise<void>;
15
16
  }) {
16
17
  const { archiveFilePath, onArchiveFile } = params;
@@ -104,11 +105,22 @@ export async function extractArchive(params: {
104
105
  break handle_file;
105
106
  }
106
107
 
108
+ let hasEarlyExitBeenCalled = false;
109
+
107
110
  await onArchiveFile({
108
111
  relativeFilePathInArchive: entry.fileName.split("/").join(pathSep),
109
112
  readFile: () => readFile(entry),
110
- writeFile: params => writeFile(entry, params)
113
+ writeFile: params => writeFile(entry, params),
114
+ earlyExit: () => {
115
+ hasEarlyExitBeenCalled = true;
116
+ }
111
117
  });
118
+
119
+ if (hasEarlyExitBeenCalled) {
120
+ zipFile.close();
121
+ dDone.resolve();
122
+ return;
123
+ }
112
124
  }
113
125
 
114
126
  zipFile.readEntry();
@@ -1799,6 +1799,7 @@ function extractArchive(params) {
1799
1799
  });
1800
1800
  };
1801
1801
  zipFile.on("entry", function (entry) { return __awaiter(_this, void 0, void 0, function () {
1802
+ var hasEarlyExitBeenCalled_1;
1802
1803
  return __generator(this, function (_a) {
1803
1804
  switch (_a.label) {
1804
1805
  case 0:
@@ -1806,13 +1807,22 @@ function extractArchive(params) {
1806
1807
  if (entry.fileName.endsWith(path_1.sep)) {
1807
1808
  return [3 /*break*/, 2];
1808
1809
  }
1810
+ hasEarlyExitBeenCalled_1 = false;
1809
1811
  return [4 /*yield*/, onArchiveFile({
1810
1812
  relativeFilePathInArchive: entry.fileName.split("/").join(path_1.sep),
1811
1813
  readFile: function () { return readFile(entry); },
1812
- writeFile: function (params) { return writeFile(entry, params); }
1814
+ writeFile: function (params) { return writeFile(entry, params); },
1815
+ earlyExit: function () {
1816
+ hasEarlyExitBeenCalled_1 = true;
1817
+ }
1813
1818
  })];
1814
1819
  case 1:
1815
1820
  _a.sent();
1821
+ if (hasEarlyExitBeenCalled_1) {
1822
+ zipFile.close();
1823
+ dDone.resolve();
1824
+ return [2 /*return*/];
1825
+ }
1816
1826
  _a.label = 2;
1817
1827
  case 2:
1818
1828
  zipFile.readEntry();