keycloakify 11.6.0 → 11.6.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/{805.index.js → 174.index.js} +111 -2
- package/bin/{356.index.js → 300.index.js} +19 -4
- package/bin/{33.index.js → 568.index.js} +2 -113
- package/bin/615.index.js +1009 -0
- package/bin/653.index.js +53 -135
- package/bin/735.index.js +53 -24
- package/bin/854.index.js +1 -1
- package/bin/921.index.js +1 -1
- package/bin/initialize-admin-theme.d.ts +4 -0
- package/bin/main.js +17 -5
- package/bin/shared/addPostinstallScriptIfNotPresent.d.ts +10 -0
- package/bin/shared/customHandler.d.ts +1 -1
- package/bin/shared/customHandler.js.map +1 -1
- package/bin/tools/npmInstall.d.ts +1 -1
- package/package.json +9 -4
- package/src/bin/initialize-account-theme/initializeAccountTheme_singlePage.ts +3 -1
- package/src/bin/initialize-admin-theme.ts +146 -0
- package/src/bin/main.ts +15 -1
- package/src/bin/postinstall/installUiModulesPeerDependencies.ts +1 -1
- package/src/bin/postinstall/uiModuleMeta.ts +7 -1
- package/src/bin/shared/addPostinstallScriptIfNotPresent.ts +70 -0
- package/src/bin/shared/customHandler.ts +1 -0
- package/src/bin/tools/npmInstall.ts +46 -9
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "keycloakify",
|
3
|
-
"version": "11.6.
|
3
|
+
"version": "11.6.1",
|
4
4
|
"description": "Framework to create custom Keycloak UIs",
|
5
5
|
"repository": {
|
6
6
|
"type": "git",
|
@@ -661,6 +661,7 @@
|
|
661
661
|
"src/bin/initialize-account-theme/src/single-page/KcContext.ts",
|
662
662
|
"src/bin/initialize-account-theme/src/single-page/KcPage.tsx",
|
663
663
|
"src/bin/initialize-account-theme/updateAccountThemeImplementationInConfig.ts",
|
664
|
+
"src/bin/initialize-admin-theme.ts",
|
664
665
|
"src/bin/initialize-email-theme.ts",
|
665
666
|
"src/bin/keycloakify/buildJars/buildJar.ts",
|
666
667
|
"src/bin/keycloakify/buildJars/buildJars.ts",
|
@@ -691,6 +692,7 @@
|
|
691
692
|
"src/bin/postinstall/postinstall.ts",
|
692
693
|
"src/bin/postinstall/uiModuleMeta.ts",
|
693
694
|
"src/bin/shared/KeycloakVersionRange.ts",
|
695
|
+
"src/bin/shared/addPostinstallScriptIfNotPresent.ts",
|
694
696
|
"src/bin/shared/buildContext.ts",
|
695
697
|
"src/bin/shared/constants.ts",
|
696
698
|
"src/bin/shared/customHandler.ts",
|
@@ -1042,6 +1044,7 @@
|
|
1042
1044
|
"bin/initialize-account-theme/initializeAccountTheme_multiPage.d.ts",
|
1043
1045
|
"bin/initialize-account-theme/initializeAccountTheme_singlePage.d.ts",
|
1044
1046
|
"bin/initialize-account-theme/updateAccountThemeImplementationInConfig.d.ts",
|
1047
|
+
"bin/initialize-admin-theme.d.ts",
|
1045
1048
|
"bin/initialize-email-theme.d.ts",
|
1046
1049
|
"bin/keycloakify/buildJars/buildJar.d.ts",
|
1047
1050
|
"bin/keycloakify/buildJars/buildJars.d.ts",
|
@@ -1070,6 +1073,7 @@
|
|
1070
1073
|
"bin/postinstall/managedGitignoreFile.d.ts",
|
1071
1074
|
"bin/postinstall/postinstall.d.ts",
|
1072
1075
|
"bin/postinstall/uiModuleMeta.d.ts",
|
1076
|
+
"bin/shared/addPostinstallScriptIfNotPresent.d.ts",
|
1073
1077
|
"bin/shared/buildContext.d.ts",
|
1074
1078
|
"bin/shared/constants.d.ts",
|
1075
1079
|
"bin/shared/customHandler_delegate.d.ts",
|
@@ -1134,16 +1138,18 @@
|
|
1134
1138
|
"bin/update-kc-gen.d.ts",
|
1135
1139
|
"bin/main.js",
|
1136
1140
|
"bin/153.index.js",
|
1141
|
+
"bin/174.index.js",
|
1137
1142
|
"bin/266.index.js",
|
1143
|
+
"bin/300.index.js",
|
1138
1144
|
"bin/304.index.js",
|
1139
|
-
"bin/33.index.js",
|
1140
|
-
"bin/356.index.js",
|
1141
1145
|
"bin/375.index.js",
|
1142
1146
|
"bin/40.index.js",
|
1143
1147
|
"bin/453.index.js",
|
1144
1148
|
"bin/490.index.js",
|
1145
1149
|
"bin/503.index.js",
|
1146
1150
|
"bin/525.index.js",
|
1151
|
+
"bin/568.index.js",
|
1152
|
+
"bin/615.index.js",
|
1147
1153
|
"bin/653.index.js",
|
1148
1154
|
"bin/658.index.js",
|
1149
1155
|
"bin/720.index.js",
|
@@ -1151,7 +1157,6 @@
|
|
1151
1157
|
"bin/743.index.js",
|
1152
1158
|
"bin/783.index.js",
|
1153
1159
|
"bin/786.index.js",
|
1154
|
-
"bin/805.index.js",
|
1155
1160
|
"bin/854.index.js",
|
1156
1161
|
"bin/877.index.js",
|
1157
1162
|
"bin/880.index.js",
|
@@ -119,7 +119,9 @@ export async function initializeAccountTheme_singlePage(params: {
|
|
119
119
|
JSON.stringify(parsedPackageJson, undefined, 4)
|
120
120
|
);
|
121
121
|
|
122
|
-
npmInstall({
|
122
|
+
await npmInstall({
|
123
|
+
packageJsonDirPath: pathDirname(buildContext.packageJsonFilePath)
|
124
|
+
});
|
123
125
|
|
124
126
|
copyBoilerplate({
|
125
127
|
accountThemeType: "Single-Page",
|
@@ -0,0 +1,146 @@
|
|
1
|
+
import { dirname as pathDirname, join as pathJoin, relative as pathRelative } from "path";
|
2
|
+
import type { BuildContext } from "./shared/buildContext";
|
3
|
+
import * as fs from "fs";
|
4
|
+
import { maybeDelegateCommandToCustomHandler } from "./shared/customHandler_delegate";
|
5
|
+
import { assert, is, type Equals } from "tsafe/assert";
|
6
|
+
import { id } from "tsafe/id";
|
7
|
+
import { addPostinstallScriptIfNotPresent } from "./shared/addPostinstallScriptIfNotPresent";
|
8
|
+
import { getIsPrettierAvailable, runPrettier } from "./tools/runPrettier";
|
9
|
+
import { npmInstall } from "./tools/npmInstall";
|
10
|
+
import * as child_process from "child_process";
|
11
|
+
import { z } from "zod";
|
12
|
+
import chalk from "chalk";
|
13
|
+
|
14
|
+
export async function command(params: { buildContext: BuildContext }) {
|
15
|
+
const { buildContext } = params;
|
16
|
+
|
17
|
+
const { hasBeenHandled } = maybeDelegateCommandToCustomHandler({
|
18
|
+
commandName: "initialize-admin-theme",
|
19
|
+
buildContext
|
20
|
+
});
|
21
|
+
|
22
|
+
if (hasBeenHandled) {
|
23
|
+
return;
|
24
|
+
}
|
25
|
+
|
26
|
+
{
|
27
|
+
const adminThemeSrcDirPath = pathJoin(buildContext.themeSrcDirPath, "admin");
|
28
|
+
|
29
|
+
if (
|
30
|
+
fs.existsSync(adminThemeSrcDirPath) &&
|
31
|
+
fs.readdirSync(adminThemeSrcDirPath).length > 0
|
32
|
+
) {
|
33
|
+
console.warn(
|
34
|
+
chalk.red(
|
35
|
+
`There is already a ${pathRelative(
|
36
|
+
process.cwd(),
|
37
|
+
adminThemeSrcDirPath
|
38
|
+
)} directory in your project. Aborting.`
|
39
|
+
)
|
40
|
+
);
|
41
|
+
|
42
|
+
process.exit(-1);
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
const parsedPackageJson = (() => {
|
47
|
+
type ParsedPackageJson = {
|
48
|
+
scripts?: Record<string, string | undefined>;
|
49
|
+
dependencies?: Record<string, string | undefined>;
|
50
|
+
devDependencies?: Record<string, string | undefined>;
|
51
|
+
};
|
52
|
+
|
53
|
+
const zParsedPackageJson = (() => {
|
54
|
+
type TargetType = ParsedPackageJson;
|
55
|
+
|
56
|
+
const zTargetType = z.object({
|
57
|
+
scripts: z.record(z.union([z.string(), z.undefined()])).optional(),
|
58
|
+
dependencies: z.record(z.union([z.string(), z.undefined()])).optional(),
|
59
|
+
devDependencies: z.record(z.union([z.string(), z.undefined()])).optional()
|
60
|
+
});
|
61
|
+
|
62
|
+
assert<Equals<z.infer<typeof zTargetType>, TargetType>>;
|
63
|
+
|
64
|
+
return id<z.ZodType<TargetType>>(zTargetType);
|
65
|
+
})();
|
66
|
+
const parsedPackageJson = JSON.parse(
|
67
|
+
fs.readFileSync(buildContext.packageJsonFilePath).toString("utf8")
|
68
|
+
);
|
69
|
+
|
70
|
+
zParsedPackageJson.parse(parsedPackageJson);
|
71
|
+
|
72
|
+
assert(is<ParsedPackageJson>(parsedPackageJson));
|
73
|
+
|
74
|
+
return parsedPackageJson;
|
75
|
+
})();
|
76
|
+
|
77
|
+
addPostinstallScriptIfNotPresent({
|
78
|
+
parsedPackageJson,
|
79
|
+
buildContext
|
80
|
+
});
|
81
|
+
|
82
|
+
const uiSharedMajor = (() => {
|
83
|
+
const dependencies = {
|
84
|
+
...parsedPackageJson.devDependencies,
|
85
|
+
...parsedPackageJson.dependencies
|
86
|
+
};
|
87
|
+
|
88
|
+
const version = dependencies["@keycloakify/keycloak-ui-shared"];
|
89
|
+
|
90
|
+
if (version === undefined) {
|
91
|
+
return undefined;
|
92
|
+
}
|
93
|
+
|
94
|
+
const match = version.match(/^[^~]?(\d+)\./);
|
95
|
+
|
96
|
+
if (match === null) {
|
97
|
+
return undefined;
|
98
|
+
}
|
99
|
+
|
100
|
+
return match[1];
|
101
|
+
})();
|
102
|
+
|
103
|
+
const moduleName = "@keycloakify/keycloak-admin-ui";
|
104
|
+
|
105
|
+
const version = (
|
106
|
+
JSON.parse(
|
107
|
+
child_process
|
108
|
+
.execSync(`npm show ${moduleName} versions --json`)
|
109
|
+
.toString("utf8")
|
110
|
+
.trim()
|
111
|
+
) as string[]
|
112
|
+
)
|
113
|
+
.reverse()
|
114
|
+
.filter(version => !version.includes("-"))
|
115
|
+
.find(version =>
|
116
|
+
uiSharedMajor === undefined ? true : version.startsWith(`${uiSharedMajor}.`)
|
117
|
+
);
|
118
|
+
|
119
|
+
assert(version !== undefined);
|
120
|
+
|
121
|
+
(parsedPackageJson.dependencies ??= {})[moduleName] = `~${version}`;
|
122
|
+
|
123
|
+
if (parsedPackageJson.devDependencies !== undefined) {
|
124
|
+
delete parsedPackageJson.devDependencies[moduleName];
|
125
|
+
}
|
126
|
+
|
127
|
+
{
|
128
|
+
let sourceCode = JSON.stringify(parsedPackageJson, undefined, 2);
|
129
|
+
|
130
|
+
if (await getIsPrettierAvailable()) {
|
131
|
+
sourceCode = await runPrettier({
|
132
|
+
sourceCode,
|
133
|
+
filePath: buildContext.packageJsonFilePath
|
134
|
+
});
|
135
|
+
}
|
136
|
+
|
137
|
+
fs.writeFileSync(
|
138
|
+
buildContext.packageJsonFilePath,
|
139
|
+
Buffer.from(sourceCode, "utf8")
|
140
|
+
);
|
141
|
+
}
|
142
|
+
|
143
|
+
await npmInstall({
|
144
|
+
packageJsonDirPath: pathDirname(buildContext.packageJsonFilePath)
|
145
|
+
});
|
146
|
+
}
|
package/src/bin/main.ts
CHANGED
@@ -191,7 +191,7 @@ program
|
|
191
191
|
program
|
192
192
|
.command({
|
193
193
|
name: "initialize-account-theme",
|
194
|
-
description: "Initialize
|
194
|
+
description: "Initialize an Account Single-Page or Multi-Page custom Account UI."
|
195
195
|
})
|
196
196
|
.task({
|
197
197
|
skip,
|
@@ -202,6 +202,20 @@ program
|
|
202
202
|
}
|
203
203
|
});
|
204
204
|
|
205
|
+
program
|
206
|
+
.command({
|
207
|
+
name: "initialize-admin-theme",
|
208
|
+
description: "Initialize an Admin Console custom UI."
|
209
|
+
})
|
210
|
+
.task({
|
211
|
+
skip,
|
212
|
+
handler: async ({ projectDirPath }) => {
|
213
|
+
const { command } = await import("./initialize-admin-theme");
|
214
|
+
|
215
|
+
await command({ buildContext: getBuildContext({ projectDirPath }) });
|
216
|
+
}
|
217
|
+
});
|
218
|
+
|
205
219
|
program
|
206
220
|
.command({
|
207
221
|
name: "copy-keycloak-resources-to-public",
|
@@ -149,7 +149,7 @@ export async function installUiModulesPeerDependencies(params: {
|
|
149
149
|
|
150
150
|
await fsPr.writeFile(buildContext.packageJsonFilePath, packageJsonContentStr);
|
151
151
|
|
152
|
-
npmInstall({
|
152
|
+
await npmInstall({
|
153
153
|
packageJsonDirPath: pathDirname(buildContext.packageJsonFilePath)
|
154
154
|
});
|
155
155
|
|
@@ -16,6 +16,7 @@ import {
|
|
16
16
|
import * as crypto from "crypto";
|
17
17
|
import { KEYCLOAK_THEME } from "../shared/constants";
|
18
18
|
import { exclude } from "tsafe/exclude";
|
19
|
+
import { isAmong } from "tsafe/isAmong";
|
19
20
|
|
20
21
|
export type UiModuleMeta = {
|
21
22
|
moduleName: string;
|
@@ -264,7 +265,12 @@ export async function getUiModuleMetas(params: {
|
|
264
265
|
moduleName,
|
265
266
|
version,
|
266
267
|
files,
|
267
|
-
peerDependencies
|
268
|
+
peerDependencies: Object.fromEntries(
|
269
|
+
Object.entries(peerDependencies).filter(
|
270
|
+
([moduleName]) =>
|
271
|
+
!isAmong(["react", "@types/react"], moduleName)
|
272
|
+
)
|
273
|
+
)
|
268
274
|
});
|
269
275
|
}
|
270
276
|
)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
import { dirname as pathDirname, relative as pathRelative, sep as pathSep } from "path";
|
2
|
+
import { assert } from "tsafe/assert";
|
3
|
+
import type { BuildContext } from "./buildContext";
|
4
|
+
|
5
|
+
export type BuildContextLike = {
|
6
|
+
projectDirPath: string;
|
7
|
+
packageJsonFilePath: string;
|
8
|
+
};
|
9
|
+
|
10
|
+
assert<BuildContext extends BuildContextLike ? true : false>();
|
11
|
+
|
12
|
+
export function addPostinstallScriptIfNotPresent(params: {
|
13
|
+
parsedPackageJson: { scripts?: Record<string, string | undefined> };
|
14
|
+
buildContext: BuildContextLike;
|
15
|
+
}) {
|
16
|
+
const { parsedPackageJson, buildContext } = params;
|
17
|
+
|
18
|
+
const cmd_base = "keycloakify postinstall";
|
19
|
+
|
20
|
+
const projectCliOptionValue = (() => {
|
21
|
+
const packageJsonDirPath = pathDirname(buildContext.packageJsonFilePath);
|
22
|
+
|
23
|
+
const relativePath = pathRelative(
|
24
|
+
packageJsonDirPath,
|
25
|
+
buildContext.projectDirPath
|
26
|
+
);
|
27
|
+
|
28
|
+
if (relativePath === "") {
|
29
|
+
return undefined;
|
30
|
+
}
|
31
|
+
|
32
|
+
return relativePath.split(pathSep).join("/");
|
33
|
+
})();
|
34
|
+
|
35
|
+
const generateCmd = (params: { cmd_preexisting: string | undefined }) => {
|
36
|
+
const { cmd_preexisting } = params;
|
37
|
+
|
38
|
+
let cmd = cmd_preexisting === undefined ? "" : `${cmd_preexisting} && `;
|
39
|
+
|
40
|
+
cmd += cmd_base;
|
41
|
+
|
42
|
+
if (projectCliOptionValue !== undefined) {
|
43
|
+
cmd += ` -p ${projectCliOptionValue}`;
|
44
|
+
}
|
45
|
+
|
46
|
+
return cmd;
|
47
|
+
};
|
48
|
+
|
49
|
+
{
|
50
|
+
const scripts = (parsedPackageJson.scripts ??= {});
|
51
|
+
|
52
|
+
for (const scriptName of ["postinstall", "prepare"]) {
|
53
|
+
const cmd_preexisting = scripts[scriptName];
|
54
|
+
|
55
|
+
if (cmd_preexisting === undefined) {
|
56
|
+
continue;
|
57
|
+
}
|
58
|
+
|
59
|
+
if (cmd_preexisting.includes(cmd_base)) {
|
60
|
+
scripts[scriptName] = generateCmd({ cmd_preexisting });
|
61
|
+
return;
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
parsedPackageJson.scripts = {
|
67
|
+
postinstall: generateCmd({ cmd_preexisting: undefined }),
|
68
|
+
...parsedPackageJson.scripts
|
69
|
+
};
|
70
|
+
}
|
@@ -9,8 +9,9 @@ import { objectKeys } from "tsafe/objectKeys";
|
|
9
9
|
import { getAbsoluteAndInOsFormatPath } from "./getAbsoluteAndInOsFormatPath";
|
10
10
|
import { exclude } from "tsafe/exclude";
|
11
11
|
import { rmSync } from "./fs.rmSync";
|
12
|
+
import { Deferred } from "evt/tools/Deferred";
|
12
13
|
|
13
|
-
export function npmInstall(params: { packageJsonDirPath: string }) {
|
14
|
+
export async function npmInstall(params: { packageJsonDirPath: string }) {
|
14
15
|
const { packageJsonDirPath } = params;
|
15
16
|
|
16
17
|
const packageManagerBinName = (() => {
|
@@ -68,7 +69,7 @@ export function npmInstall(params: { packageJsonDirPath: string }) {
|
|
68
69
|
|
69
70
|
console.log(chalk.green("Installing in a way that won't break the links..."));
|
70
71
|
|
71
|
-
installWithoutBreakingLinks({
|
72
|
+
await installWithoutBreakingLinks({
|
72
73
|
packageJsonDirPath,
|
73
74
|
garronejLinkInfos
|
74
75
|
});
|
@@ -77,9 +78,9 @@ export function npmInstall(params: { packageJsonDirPath: string }) {
|
|
77
78
|
}
|
78
79
|
|
79
80
|
try {
|
80
|
-
|
81
|
-
|
82
|
-
|
81
|
+
await runPackageManagerInstall({
|
82
|
+
packageManagerBinName,
|
83
|
+
cwd: packageJsonDirPath
|
83
84
|
});
|
84
85
|
} catch {
|
85
86
|
console.log(
|
@@ -90,6 +91,42 @@ export function npmInstall(params: { packageJsonDirPath: string }) {
|
|
90
91
|
}
|
91
92
|
}
|
92
93
|
|
94
|
+
async function runPackageManagerInstall(params: {
|
95
|
+
packageManagerBinName: string;
|
96
|
+
cwd: string;
|
97
|
+
}) {
|
98
|
+
const { packageManagerBinName, cwd } = params;
|
99
|
+
|
100
|
+
const dCompleted = new Deferred<void>();
|
101
|
+
|
102
|
+
const child = child_process.spawn(packageManagerBinName, ["install"], {
|
103
|
+
cwd,
|
104
|
+
env: process.env,
|
105
|
+
shell: true
|
106
|
+
});
|
107
|
+
|
108
|
+
child.stdout.on("data", data => process.stdout.write(data));
|
109
|
+
|
110
|
+
child.stderr.on("data", data => {
|
111
|
+
if (data.toString("utf8").includes("has unmet peer dependency")) {
|
112
|
+
return;
|
113
|
+
}
|
114
|
+
|
115
|
+
process.stderr.write(data);
|
116
|
+
});
|
117
|
+
|
118
|
+
child.on("exit", code => {
|
119
|
+
if (code !== 0) {
|
120
|
+
dCompleted.reject(new Error(`Failed with code ${code}`));
|
121
|
+
return;
|
122
|
+
}
|
123
|
+
|
124
|
+
dCompleted.resolve();
|
125
|
+
});
|
126
|
+
|
127
|
+
await dCompleted.pr;
|
128
|
+
}
|
129
|
+
|
93
130
|
function getGarronejLinkInfos(params: {
|
94
131
|
packageJsonDirPath: string;
|
95
132
|
}): { linkedModuleNames: string[]; yarnHomeDirPath: string } | undefined {
|
@@ -180,7 +217,7 @@ function getGarronejLinkInfos(params: {
|
|
180
217
|
return { linkedModuleNames, yarnHomeDirPath };
|
181
218
|
}
|
182
219
|
|
183
|
-
function installWithoutBreakingLinks(params: {
|
220
|
+
async function installWithoutBreakingLinks(params: {
|
184
221
|
packageJsonDirPath: string;
|
185
222
|
garronejLinkInfos: Exclude<ReturnType<typeof getGarronejLinkInfos>, undefined>;
|
186
223
|
}) {
|
@@ -261,9 +298,9 @@ function installWithoutBreakingLinks(params: {
|
|
261
298
|
pathJoin(tmpProjectDirPath, YARN_LOCK)
|
262
299
|
);
|
263
300
|
|
264
|
-
|
265
|
-
|
266
|
-
|
301
|
+
await runPackageManagerInstall({
|
302
|
+
packageManagerBinName: "yarn",
|
303
|
+
cwd: tmpProjectDirPath
|
267
304
|
});
|
268
305
|
|
269
306
|
// NOTE: Moving the modules from the tmp project to the actual project
|