keycloakify 10.0.0-rc.90 → 10.0.0-rc.92
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/193.index.js +3 -3
- package/bin/{751.index.js → 31.index.js} +183 -131
- package/bin/440.index.js +7 -12
- package/bin/453.index.js +1 -1
- package/bin/526.index.js +79 -68
- package/bin/538.index.js +1 -1
- package/bin/{837.index.js → 893.index.js} +7 -89
- package/bin/932.index.js +2 -2
- package/bin/97.index.js +1 -1
- package/bin/main.js +7 -7
- package/bin/shared/buildContext.d.ts +9 -2
- package/bin/shared/buildContext.js.map +1 -1
- package/bin/shared/copyKeycloakResourcesToPublic.js.map +1 -1
- package/bin/shared/downloadKeycloakDefaultTheme.d.ts +2 -1
- package/bin/shared/downloadKeycloakDefaultTheme.js.map +1 -1
- package/package.json +7 -9
- package/src/bin/keycloakify/generateFtl/generateFtl.ts +14 -10
- package/src/bin/keycloakify/generateResources/generateResourcesForMainTheme.ts +2 -1
- package/src/bin/keycloakify/keycloakify.ts +1 -7
- package/src/bin/keycloakify/replacers/replaceImportsInJsCode/replaceImportsInJsCode.ts +2 -2
- package/src/bin/shared/buildContext.ts +170 -92
- package/src/bin/shared/copyKeycloakResourcesToPublic.ts +1 -4
- package/src/bin/shared/downloadKeycloakDefaultTheme.ts +2 -2
- package/src/bin/start-keycloak/appBuild.ts +131 -94
- package/src/bin/start-keycloak/keycloakifyBuild.ts +0 -1
- package/src/bin/start-keycloak/start-keycloak.ts +1 -1
- package/src/bin/tools/{downloadAndExtractArchive/downloadAndExtractArchive.ts → downloadAndExtractArchive.ts} +9 -17
- package/src/bin/tools/{downloadAndExtractArchive/fetchProxyOptions.ts → fetchProxyOptions.ts} +52 -60
- package/vite-plugin/index.js +190 -228
- package/src/bin/tools/downloadAndExtractArchive/index.ts +0 -1
- package/src/bin/tools/getNpmWorkspaceRootDirPath.ts +0 -84
@@ -1,16 +1,14 @@
|
|
1
1
|
import * as child_process from "child_process";
|
2
2
|
import { Deferred } from "evt/tools/Deferred";
|
3
3
|
import { assert } from "tsafe/assert";
|
4
|
-
import { is } from "tsafe/is";
|
5
4
|
import type { BuildContext } from "../shared/buildContext";
|
6
|
-
import
|
7
|
-
import { join as pathJoin } from "path";
|
5
|
+
import chalk from "chalk";
|
6
|
+
import { sep as pathSep, join as pathJoin } from "path";
|
8
7
|
|
9
8
|
export type BuildContextLike = {
|
10
9
|
projectDirPath: string;
|
11
10
|
keycloakifyBuildDirPath: string;
|
12
|
-
bundler: "
|
13
|
-
npmWorkspaceRootDirPath: string;
|
11
|
+
bundler: BuildContext["bundler"];
|
14
12
|
projectBuildDirPath: string;
|
15
13
|
};
|
16
14
|
|
@@ -21,95 +19,29 @@ export async function appBuild(params: {
|
|
21
19
|
}): Promise<{ isAppBuildSuccess: boolean }> {
|
22
20
|
const { buildContext } = params;
|
23
21
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
]) {
|
39
|
-
try {
|
40
|
-
const parsedPackageJson = JSON.parse(
|
41
|
-
fs
|
42
|
-
.readFileSync(pathJoin(dirPath, "package.json"))
|
43
|
-
.toString("utf8")
|
44
|
-
);
|
45
|
-
|
46
|
-
const [scriptName] =
|
47
|
-
Object.entries(parsedPackageJson.scripts).find(
|
48
|
-
([, scriptValue]) => {
|
49
|
-
assert(is<string>(scriptValue));
|
50
|
-
if (
|
51
|
-
scriptValue.includes("webpack") &&
|
52
|
-
scriptValue.includes("--mode production")
|
53
|
-
) {
|
54
|
-
return true;
|
55
|
-
}
|
56
|
-
|
57
|
-
if (
|
58
|
-
scriptValue.includes("react-scripts") &&
|
59
|
-
scriptValue.includes("build")
|
60
|
-
) {
|
61
|
-
return true;
|
62
|
-
}
|
63
|
-
|
64
|
-
if (
|
65
|
-
scriptValue.includes("react-app-rewired") &&
|
66
|
-
scriptValue.includes("build")
|
67
|
-
) {
|
68
|
-
return true;
|
69
|
-
}
|
70
|
-
|
71
|
-
if (
|
72
|
-
scriptValue.includes("craco") &&
|
73
|
-
scriptValue.includes("build")
|
74
|
-
) {
|
75
|
-
return true;
|
76
|
-
}
|
77
|
-
|
78
|
-
if (
|
79
|
-
scriptValue.includes("ng") &&
|
80
|
-
scriptValue.includes("build")
|
81
|
-
) {
|
82
|
-
return true;
|
83
|
-
}
|
84
|
-
|
85
|
-
return false;
|
86
|
-
}
|
87
|
-
) ?? [];
|
88
|
-
|
89
|
-
if (scriptName === undefined) {
|
90
|
-
continue;
|
91
|
-
}
|
92
|
-
|
93
|
-
return {
|
94
|
-
command: "npm",
|
95
|
-
args: ["run", scriptName],
|
96
|
-
cwd: dirPath
|
97
|
-
};
|
98
|
-
} catch {
|
99
|
-
continue;
|
100
|
-
}
|
101
|
-
}
|
102
|
-
|
103
|
-
throw new Error(
|
104
|
-
"Keycloakify was unable to determine which script is responsible for building the app."
|
105
|
-
);
|
106
|
-
}
|
107
|
-
}
|
108
|
-
})();
|
22
|
+
switch (buildContext.bundler.type) {
|
23
|
+
case "vite":
|
24
|
+
return appBuild_vite({ buildContext });
|
25
|
+
case "webpack":
|
26
|
+
return appBuild_webpack({ buildContext });
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
async function appBuild_vite(params: {
|
31
|
+
buildContext: BuildContextLike;
|
32
|
+
}): Promise<{ isAppBuildSuccess: boolean }> {
|
33
|
+
const { buildContext } = params;
|
34
|
+
|
35
|
+
assert(buildContext.bundler.type === "vite");
|
109
36
|
|
110
|
-
const
|
37
|
+
const dIsSuccess = new Deferred<boolean>();
|
111
38
|
|
112
|
-
|
39
|
+
console.log(chalk.blue("Running: 'npx vite build'"));
|
40
|
+
|
41
|
+
const child = child_process.spawn("npx", ["vite", "build"], {
|
42
|
+
cwd: buildContext.projectDirPath,
|
43
|
+
shell: true
|
44
|
+
});
|
113
45
|
|
114
46
|
child.stdout.on("data", data => {
|
115
47
|
if (data.toString("utf8").includes("gzip:")) {
|
@@ -121,9 +53,114 @@ export async function appBuild(params: {
|
|
121
53
|
|
122
54
|
child.stderr.on("data", data => process.stderr.write(data));
|
123
55
|
|
124
|
-
child.on("exit", code =>
|
56
|
+
child.on("exit", code => dIsSuccess.resolve(code === 0));
|
125
57
|
|
126
|
-
const
|
58
|
+
const isSuccess = await dIsSuccess.pr;
|
127
59
|
|
128
60
|
return { isAppBuildSuccess: isSuccess };
|
129
61
|
}
|
62
|
+
|
63
|
+
async function appBuild_webpack(params: {
|
64
|
+
buildContext: BuildContextLike;
|
65
|
+
}): Promise<{ isAppBuildSuccess: boolean }> {
|
66
|
+
const { buildContext } = params;
|
67
|
+
|
68
|
+
assert(buildContext.bundler.type === "webpack");
|
69
|
+
|
70
|
+
const entries = Object.entries(buildContext.bundler.packageJsonScripts).filter(
|
71
|
+
([, scriptCommand]) => scriptCommand.includes("keycloakify build")
|
72
|
+
);
|
73
|
+
|
74
|
+
if (entries.length === 0) {
|
75
|
+
console.log(
|
76
|
+
chalk.red(
|
77
|
+
[
|
78
|
+
`You should have a script in your package.json at ${buildContext.bundler.packageJsonDirPath}`,
|
79
|
+
`that includes the 'keycloakify build' command`
|
80
|
+
].join(" ")
|
81
|
+
)
|
82
|
+
);
|
83
|
+
process.exit(-1);
|
84
|
+
}
|
85
|
+
|
86
|
+
const entry =
|
87
|
+
entries.length === 1
|
88
|
+
? entries[0]
|
89
|
+
: entries.find(([scriptName]) => scriptName === "build-keycloak-theme");
|
90
|
+
|
91
|
+
if (entry === undefined) {
|
92
|
+
console.log(
|
93
|
+
chalk.red(
|
94
|
+
"There's multiple candidate script for building your app, name one 'build-keycloak-theme'"
|
95
|
+
)
|
96
|
+
);
|
97
|
+
process.exit(-1);
|
98
|
+
}
|
99
|
+
|
100
|
+
const [scriptName, scriptCommand] = entry;
|
101
|
+
|
102
|
+
const { appBuildSubCommands } = (() => {
|
103
|
+
const appBuildSubCommands: string[] = [];
|
104
|
+
|
105
|
+
for (const subCmd of scriptCommand.split("&&").map(s => s.trim())) {
|
106
|
+
if (subCmd.includes("keycloakify build")) {
|
107
|
+
break;
|
108
|
+
}
|
109
|
+
|
110
|
+
appBuildSubCommands.push(subCmd);
|
111
|
+
}
|
112
|
+
|
113
|
+
return { appBuildSubCommands };
|
114
|
+
})();
|
115
|
+
|
116
|
+
if (appBuildSubCommands.length === 0) {
|
117
|
+
console.log(
|
118
|
+
chalk.red(
|
119
|
+
`Your ${scriptName} script should look like "... && keycloakify build ..."`
|
120
|
+
)
|
121
|
+
);
|
122
|
+
process.exit(-1);
|
123
|
+
}
|
124
|
+
|
125
|
+
for (const subCommand of appBuildSubCommands) {
|
126
|
+
const dIsSuccess = new Deferred<boolean>();
|
127
|
+
|
128
|
+
console.log(chalk.blue(`Running: '${subCommand}'`));
|
129
|
+
|
130
|
+
const [command, ...args] = subCommand.split(" ");
|
131
|
+
|
132
|
+
const child = child_process.spawn(command, args, {
|
133
|
+
cwd: buildContext.bundler.packageJsonDirPath,
|
134
|
+
env: {
|
135
|
+
...process.env,
|
136
|
+
PATH: (() => {
|
137
|
+
const separator = pathSep === "/" ? ":" : ";";
|
138
|
+
|
139
|
+
return [
|
140
|
+
pathJoin(
|
141
|
+
buildContext.bundler.packageJsonDirPath,
|
142
|
+
"node_modules",
|
143
|
+
".bin"
|
144
|
+
),
|
145
|
+
...(process.env.PATH ?? "").split(separator)
|
146
|
+
].join(separator);
|
147
|
+
})()
|
148
|
+
},
|
149
|
+
shell: true
|
150
|
+
});
|
151
|
+
|
152
|
+
child.stdout.on("data", data => process.stdout.write(data));
|
153
|
+
|
154
|
+
child.stderr.on("data", data => process.stderr.write(data));
|
155
|
+
|
156
|
+
child.on("exit", code => dIsSuccess.resolve(code === 0));
|
157
|
+
|
158
|
+
const isSuccess = await dIsSuccess.pr;
|
159
|
+
|
160
|
+
if (!isSuccess) {
|
161
|
+
return { isAppBuildSuccess: false };
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
return { isAppBuildSuccess: true };
|
166
|
+
}
|
@@ -121,7 +121,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
|
|
121
121
|
if (!isAppBuildSuccess) {
|
122
122
|
console.log(
|
123
123
|
chalk.red(
|
124
|
-
`App build failed, exiting. Try
|
124
|
+
`App build failed, exiting. Try building your app (e.g 'npm run build') and see what's wrong.`
|
125
125
|
)
|
126
126
|
);
|
127
127
|
process.exit(1);
|
@@ -1,12 +1,12 @@
|
|
1
|
-
import fetch from "make-fetch-happen";
|
1
|
+
import fetch, { type FetchOptions } from "make-fetch-happen";
|
2
2
|
import { mkdir, unlink, writeFile, readdir, readFile } from "fs/promises";
|
3
3
|
import { dirname as pathDirname, join as pathJoin } from "path";
|
4
4
|
import { assert } from "tsafe/assert";
|
5
|
-
import { extractArchive } from "
|
6
|
-
import { existsAsync } from "
|
7
|
-
|
5
|
+
import { extractArchive } from "./extractArchive";
|
6
|
+
import { existsAsync } from "./fs.existsAsync";
|
7
|
+
|
8
8
|
import * as crypto from "crypto";
|
9
|
-
import { rm } from "
|
9
|
+
import { rm } from "./fs.rm";
|
10
10
|
|
11
11
|
export async function downloadAndExtractArchive(params: {
|
12
12
|
url: string;
|
@@ -20,15 +20,10 @@ export async function downloadAndExtractArchive(params: {
|
|
20
20
|
}) => Promise<void>;
|
21
21
|
}) => Promise<void>;
|
22
22
|
cacheDirPath: string;
|
23
|
-
|
23
|
+
fetchOptions: FetchOptions | undefined;
|
24
24
|
}): Promise<{ extractedDirPath: string }> {
|
25
|
-
const {
|
26
|
-
|
27
|
-
uniqueIdOfOnOnArchiveFile,
|
28
|
-
onArchiveFile,
|
29
|
-
cacheDirPath,
|
30
|
-
npmWorkspaceRootDirPath
|
31
|
-
} = params;
|
25
|
+
const { url, uniqueIdOfOnOnArchiveFile, onArchiveFile, cacheDirPath, fetchOptions } =
|
26
|
+
params;
|
32
27
|
|
33
28
|
const archiveFileBasename = url.split("?")[0].split("/").reverse()[0];
|
34
29
|
|
@@ -55,10 +50,7 @@ export async function downloadAndExtractArchive(params: {
|
|
55
50
|
|
56
51
|
await mkdir(pathDirname(archiveFilePath), { recursive: true });
|
57
52
|
|
58
|
-
const response = await fetch(
|
59
|
-
url,
|
60
|
-
await getProxyFetchOptions({ npmWorkspaceRootDirPath })
|
61
|
-
);
|
53
|
+
const response = await fetch(url, fetchOptions);
|
62
54
|
|
63
55
|
response.body?.setMaxListeners(Number.MAX_VALUE);
|
64
56
|
assert(typeof response.body !== "undefined" && response.body != null);
|
package/src/bin/tools/{downloadAndExtractArchive/fetchProxyOptions.ts → fetchProxyOptions.ts}
RENAMED
@@ -1,61 +1,40 @@
|
|
1
|
-
import { exec as execCallback } from "child_process";
|
2
|
-
import { readFile } from "fs/promises";
|
3
1
|
import { type FetchOptions } from "make-fetch-happen";
|
4
|
-
import
|
5
|
-
|
6
|
-
function ensureArray<T>(arg0: T | T[]) {
|
7
|
-
return Array.isArray(arg0) ? arg0 : typeof arg0 === "undefined" ? [] : [arg0];
|
8
|
-
}
|
9
|
-
|
10
|
-
function ensureSingleOrNone<T>(arg0: T | T[]) {
|
11
|
-
if (!Array.isArray(arg0)) return arg0;
|
12
|
-
if (arg0.length === 0) return undefined;
|
13
|
-
if (arg0.length === 1) return arg0[0];
|
14
|
-
throw new Error(
|
15
|
-
"Illegal configuration, expected a single value but found multiple: " +
|
16
|
-
arg0.map(String).join(", ")
|
17
|
-
);
|
18
|
-
}
|
19
|
-
|
20
|
-
type NPMConfig = Record<string, string | string[]>;
|
21
|
-
|
22
|
-
/**
|
23
|
-
* Get npm configuration as map
|
24
|
-
*/
|
25
|
-
async function getNmpConfig(params: { npmWorkspaceRootDirPath: string }) {
|
26
|
-
const { npmWorkspaceRootDirPath } = params;
|
27
|
-
|
28
|
-
const exec = promisify(execCallback);
|
29
|
-
|
30
|
-
const stdout = await exec("npm config get", {
|
31
|
-
encoding: "utf8",
|
32
|
-
cwd: npmWorkspaceRootDirPath
|
33
|
-
}).then(({ stdout }) => stdout);
|
34
|
-
|
35
|
-
const npmConfigReducer = (cfg: NPMConfig, [key, value]: [string, string]) =>
|
36
|
-
key in cfg
|
37
|
-
? { ...cfg, [key]: [...ensureArray(cfg[key]), value] }
|
38
|
-
: { ...cfg, [key]: value };
|
39
|
-
|
40
|
-
return stdout
|
41
|
-
.split("\n")
|
42
|
-
.filter(line => !line.startsWith(";"))
|
43
|
-
.map(line => line.trim())
|
44
|
-
.map(line => line.split("=", 2) as [string, string])
|
45
|
-
.reduce(npmConfigReducer, {} as NPMConfig);
|
46
|
-
}
|
2
|
+
import * as child_process from "child_process";
|
3
|
+
import * as fs from "fs";
|
47
4
|
|
48
5
|
export type ProxyFetchOptions = Pick<
|
49
6
|
FetchOptions,
|
50
7
|
"proxy" | "noProxy" | "strictSSL" | "cert" | "ca"
|
51
8
|
>;
|
52
9
|
|
53
|
-
export
|
54
|
-
|
55
|
-
}):
|
56
|
-
const {
|
57
|
-
|
58
|
-
const cfg =
|
10
|
+
export function getProxyFetchOptions(params: {
|
11
|
+
npmConfigGetCwd: string;
|
12
|
+
}): ProxyFetchOptions {
|
13
|
+
const { npmConfigGetCwd } = params;
|
14
|
+
|
15
|
+
const cfg = (() => {
|
16
|
+
const output = child_process
|
17
|
+
.execSync("npm config get", {
|
18
|
+
cwd: npmConfigGetCwd
|
19
|
+
})
|
20
|
+
.toString("utf8");
|
21
|
+
|
22
|
+
return output
|
23
|
+
.split("\n")
|
24
|
+
.filter(line => !line.startsWith(";"))
|
25
|
+
.map(line => line.trim())
|
26
|
+
.map(line => line.split("=", 2) as [string, string])
|
27
|
+
.reduce(
|
28
|
+
(
|
29
|
+
cfg: Record<string, string | string[]>,
|
30
|
+
[key, value]: [string, string]
|
31
|
+
) =>
|
32
|
+
key in cfg
|
33
|
+
? { ...cfg, [key]: [...ensureArray(cfg[key]), value] }
|
34
|
+
: { ...cfg, [key]: value },
|
35
|
+
{}
|
36
|
+
);
|
37
|
+
})();
|
59
38
|
|
60
39
|
const proxy = ensureSingleOrNone(cfg["https-proxy"] ?? cfg["proxy"]);
|
61
40
|
const noProxy = cfg["noproxy"] ?? cfg["no-proxy"];
|
@@ -71,17 +50,16 @@ export async function getProxyFetchOptions(params: {
|
|
71
50
|
|
72
51
|
if (typeof cafile !== "undefined" && cafile !== "null") {
|
73
52
|
ca.push(
|
74
|
-
...(
|
75
|
-
|
76
|
-
return arr
|
77
|
-
.map((_, i) => i % size == 0 && arr.slice(i, i + size))
|
78
|
-
.filter(Boolean) as T[][];
|
79
|
-
}
|
80
|
-
|
81
|
-
const cafileContent = await readFile(cafile, "utf-8");
|
53
|
+
...(() => {
|
54
|
+
const cafileContent = fs.readFileSync(cafile).toString("utf8");
|
82
55
|
|
83
56
|
const newLinePlaceholder = "NEW_LINE_PLACEHOLDER_xIsPsK23svt";
|
84
57
|
|
58
|
+
const chunks = <T>(arr: T[], size: number = 2) =>
|
59
|
+
arr
|
60
|
+
.map((_, i) => i % size == 0 && arr.slice(i, i + size))
|
61
|
+
.filter(Boolean) as T[][];
|
62
|
+
|
85
63
|
return chunks(cafileContent.split(/(-----END CERTIFICATE-----)/), 2).map(
|
86
64
|
ca =>
|
87
65
|
ca
|
@@ -90,7 +68,7 @@ export async function getProxyFetchOptions(params: {
|
|
90
68
|
.replace(new RegExp(`^${newLinePlaceholder}`), "")
|
91
69
|
.replace(new RegExp(newLinePlaceholder, "g"), "\\n")
|
92
70
|
);
|
93
|
-
})()
|
71
|
+
})()
|
94
72
|
);
|
95
73
|
}
|
96
74
|
|
@@ -102,3 +80,17 @@ export async function getProxyFetchOptions(params: {
|
|
102
80
|
ca: ca.length === 0 ? undefined : ca
|
103
81
|
};
|
104
82
|
}
|
83
|
+
|
84
|
+
function ensureArray<T>(arg0: T | T[]) {
|
85
|
+
return Array.isArray(arg0) ? arg0 : typeof arg0 === "undefined" ? [] : [arg0];
|
86
|
+
}
|
87
|
+
|
88
|
+
function ensureSingleOrNone<T>(arg0: T | T[]) {
|
89
|
+
if (!Array.isArray(arg0)) return arg0;
|
90
|
+
if (arg0.length === 0) return undefined;
|
91
|
+
if (arg0.length === 1) return arg0[0];
|
92
|
+
throw new Error(
|
93
|
+
"Illegal configuration, expected a single value but found multiple: " +
|
94
|
+
arg0.map(String).join(", ")
|
95
|
+
);
|
96
|
+
}
|