keycloakify 7.3.2 → 7.4.0
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/download-builtin-keycloak-theme.js +3 -3
- package/bin/download-builtin-keycloak-theme.js.map +1 -1
- package/bin/eject-keycloak-page.js +2 -2
- package/bin/eject-keycloak-page.js.map +1 -1
- package/bin/initialize-email-theme.d.ts +1 -3
- package/bin/initialize-email-theme.js +4 -9
- package/bin/initialize-email-theme.js.map +1 -1
- package/bin/keycloakify/BuildOptions.d.ts +4 -4
- package/bin/keycloakify/BuildOptions.js +12 -28
- package/bin/keycloakify/BuildOptions.js.map +1 -1
- package/bin/keycloakify/build-paths.d.ts +12 -0
- package/bin/keycloakify/build-paths.js +93 -0
- package/bin/keycloakify/build-paths.js.map +1 -0
- package/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl +1 -2
- package/bin/keycloakify/generateFtl/generateFtl.d.ts +6 -3
- package/bin/keycloakify/generateFtl/generateFtl.js +3 -6
- package/bin/keycloakify/generateFtl/generateFtl.js.map +1 -1
- package/bin/keycloakify/generateKeycloakThemeResources.d.ts +1 -0
- package/bin/keycloakify/generateKeycloakThemeResources.js +2 -6
- package/bin/keycloakify/generateKeycloakThemeResources.js.map +1 -1
- package/bin/keycloakify/index.js +1 -1
- package/bin/keycloakify/index.js.map +1 -1
- package/bin/keycloakify/keycloakify.d.ts +0 -1
- package/bin/keycloakify/keycloakify.js +13 -15
- package/bin/keycloakify/keycloakify.js.map +1 -1
- package/bin/keycloakify/parsed-package-json.d.ts +21 -0
- package/bin/keycloakify/parsed-package-json.js +63 -0
- package/bin/keycloakify/parsed-package-json.js.map +1 -0
- package/bin/tools/downloadAndUnzip.d.ts +1 -1
- package/bin/tools/downloadAndUnzip.js +16 -16
- package/bin/tools/downloadAndUnzip.js.map +1 -1
- package/bin/tools/unzip.d.ts +1 -30
- package/bin/tools/unzip.js +99 -288
- package/bin/tools/unzip.js.map +1 -1
- package/package.json +13 -6
- package/src/bin/download-builtin-keycloak-theme.ts +3 -4
- package/src/bin/eject-keycloak-page.ts +1 -1
- package/src/bin/initialize-email-theme.ts +2 -10
- package/src/bin/keycloakify/BuildOptions.ts +15 -52
- package/src/bin/keycloakify/build-paths.ts +72 -0
- package/src/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl +1 -2
- package/src/bin/keycloakify/generateFtl/generateFtl.ts +22 -17
- package/src/bin/keycloakify/generateKeycloakThemeResources.ts +3 -7
- package/src/bin/keycloakify/index.ts +1 -1
- package/src/bin/keycloakify/keycloakify.ts +12 -16
- package/src/bin/keycloakify/parsed-package-json.ts +60 -0
- package/src/bin/tools/downloadAndUnzip.ts +5 -11
- package/src/bin/tools/unzip.ts +82 -174
- package/bin/getThemeSrcDirPath.d.ts +0 -5
- package/bin/getThemeSrcDirPath.js +0 -53
- package/bin/getThemeSrcDirPath.js.map +0 -1
- package/src/bin/getThemeSrcDirPath.ts +0 -33
package/src/bin/tools/unzip.ts
CHANGED
@@ -1,184 +1,92 @@
|
|
1
|
-
import
|
2
|
-
import
|
3
|
-
import
|
4
|
-
import
|
5
|
-
import
|
6
|
-
import {
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
*
|
18
|
-
* Will unzip using all available nodejs worker threads.
|
19
|
-
*
|
20
|
-
* Will try to clean up extracted files on failure.
|
21
|
-
*
|
22
|
-
* If unpacking fails, will either throw an regular error, or
|
23
|
-
* possibly an `MultiError`, which contains a `cause` field with
|
24
|
-
* a number of root cause errors.
|
25
|
-
*
|
26
|
-
* Warning this method is not optimized for continuous reading of the zip
|
27
|
-
* archive, but is a trade-off between simplicity and allowing extraction
|
28
|
-
* of a single directory from the archive.
|
29
|
-
*
|
30
|
-
* @param zipFilePath the file to unzip
|
31
|
-
* @param extractDirPath the target directory
|
32
|
-
* @param pathOfDirToExtractInArchive if given, unpack only files from this archive directory
|
33
|
-
* @throws {MultiError} error
|
34
|
-
* @returns Promise for a list of full file paths pointing to actually extracted files
|
35
|
-
*/
|
36
|
-
export async function unzip(zipFilePath: string, extractDirPath: string, pathOfDirToExtractInArchive?: string): Promise<string[]> {
|
37
|
-
const dirsCreated: (string | undefined)[] = [];
|
38
|
-
dirsCreated.push(await mkdir(extractDirPath, { recursive: true }));
|
39
|
-
const promises: Promise<string>[] = [];
|
40
|
-
|
41
|
-
// Iterate over all files in the zip, skip files which are not in archiveDir,
|
42
|
-
// if given.
|
43
|
-
for await (const record of iterateZipArchive(zipFilePath)) {
|
44
|
-
const { path: recordPath, createReadStream: createRecordReadStream } = record;
|
45
|
-
if (pathOfDirToExtractInArchive && !recordPath.startsWith(pathOfDirToExtractInArchive)) {
|
46
|
-
continue;
|
1
|
+
import fsp from "node:fs/promises";
|
2
|
+
import fs from "fs";
|
3
|
+
import path from "node:path";
|
4
|
+
import yauzl from "yauzl";
|
5
|
+
import stream from "node:stream";
|
6
|
+
import { promisify } from "node:util";
|
7
|
+
|
8
|
+
const pipeline = promisify(stream.pipeline);
|
9
|
+
|
10
|
+
async function pathExists(path: string) {
|
11
|
+
try {
|
12
|
+
await fsp.stat(path);
|
13
|
+
return true;
|
14
|
+
} catch (error) {
|
15
|
+
if ((error as { code: string }).code === "ENOENT") {
|
16
|
+
return false;
|
47
17
|
}
|
48
|
-
|
49
|
-
const filePath = pathJoin(extractDirPath, relativePath);
|
50
|
-
const parent = pathDirname(filePath);
|
51
|
-
promises.push(
|
52
|
-
new Promise<string>(async (resolve, reject) => {
|
53
|
-
if (!dirsCreated.includes(parent)) dirsCreated.push(await mkdir(parent, { recursive: true }));
|
54
|
-
|
55
|
-
// Pull the file out of the archive, write it to the target directory
|
56
|
-
const output = createWriteStream(filePath);
|
57
|
-
output.on("error", e => reject(Object.assign(e, { filePath })));
|
58
|
-
output.on("finish", () => resolve(filePath));
|
59
|
-
createRecordReadStream().pipe(output);
|
60
|
-
})
|
61
|
-
);
|
18
|
+
throw error;
|
62
19
|
}
|
20
|
+
}
|
63
21
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
// which has a `cause` field, containing a list of root cause errors.
|
69
|
-
if (failure.length) {
|
70
|
-
await Promise.all([
|
71
|
-
...success.map(path => unlink(path).catch(_unused => undefined)),
|
72
|
-
...failure.map(e => e && e.path && unlink(e.path as string).catch(_unused => undefined))
|
73
|
-
]);
|
74
|
-
await Promise.all(dirsCreated.filter(Boolean).sort(sortByFolderDepth("desc")));
|
75
|
-
const e = new Error("Failed to extract: " + failure.map(e => e.message).join(";"));
|
76
|
-
(e as any).cause = failure;
|
77
|
-
throw e;
|
22
|
+
export async function unzip(file: string, targetFolder: string, unzipSubPath?: string) {
|
23
|
+
// add trailing slash to unzipSubPath and targetFolder
|
24
|
+
if (unzipSubPath && (!unzipSubPath.endsWith("/") || !unzipSubPath.endsWith("\\"))) {
|
25
|
+
unzipSubPath += "/";
|
78
26
|
}
|
79
27
|
|
80
|
-
|
81
|
-
|
28
|
+
if (!targetFolder.endsWith("/") || !targetFolder.endsWith("\\")) {
|
29
|
+
targetFolder += "/";
|
30
|
+
}
|
31
|
+
if (!fs.existsSync(targetFolder)) {
|
32
|
+
fs.mkdirSync(targetFolder, { recursive: true });
|
33
|
+
}
|
82
34
|
|
83
|
-
|
84
|
-
|
85
|
-
|
35
|
+
return new Promise<void>((resolve, reject) => {
|
36
|
+
yauzl.open(file, { lazyEntries: true }, async (err, zipfile) => {
|
37
|
+
if (err) {
|
38
|
+
reject(err);
|
39
|
+
return;
|
40
|
+
}
|
86
41
|
|
87
|
-
|
88
|
-
const ord = order === "asc" ? 1 : -1;
|
89
|
-
return (a: string | undefined, b: string | undefined) => ord * depth(a ?? "") + -ord * depth(b ?? "");
|
90
|
-
}
|
42
|
+
zipfile.readEntry();
|
91
43
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
async function readFileChunk(file: string, start: number, end: number): Promise<Buffer> {
|
100
|
-
const chunks: Buffer[] = [];
|
101
|
-
return new Promise((resolve, reject) => {
|
102
|
-
const stream = createReadStream(file, { start, end });
|
103
|
-
stream.setMaxListeners(Infinity);
|
104
|
-
stream.on("error", e => reject(e));
|
105
|
-
stream.on("end", () => resolve(Buffer.concat(chunks)));
|
106
|
-
stream.on("data", chunk => chunks.push(chunk as Buffer));
|
107
|
-
});
|
108
|
-
}
|
44
|
+
zipfile.on("entry", async entry => {
|
45
|
+
if (unzipSubPath) {
|
46
|
+
// Skip files outside of the unzipSubPath
|
47
|
+
if (!entry.fileName.startsWith(unzipSubPath)) {
|
48
|
+
zipfile.readEntry();
|
49
|
+
return;
|
50
|
+
}
|
109
51
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
if (directoryOffset > size) throw new Error(`Central directory offset ${directoryOffset} is outside file`);
|
151
|
-
i = directoryOffset - unread;
|
152
|
-
// If i < 0, it means that the central directory is not contained within `chunk`
|
153
|
-
if (i < 0) {
|
154
|
-
chunk = await readFileChunk(zipFile, directoryOffset, directoryOffset + directorySize);
|
155
|
-
i = 0;
|
156
|
-
}
|
157
|
-
// Now iterate the central directory records, yield an `ZipRecord` for every entry
|
158
|
-
while (nFiles-- > 0) {
|
159
|
-
// Check for marker bytes
|
160
|
-
if (chunk.readUInt32LE(i) !== 0x02014b50) throw new Error("No central directory record at position " + (unread + i));
|
161
|
-
const compressionMethod = ({ 8: "deflate" } as const)[chunk.readUint16LE(i + 10)];
|
162
|
-
const compressedFileSize = chunk.readUint32LE(i + 20);
|
163
|
-
const filenameLength = chunk.readUint16LE(i + 28);
|
164
|
-
const extraLength = chunk.readUint16LE(i + 30);
|
165
|
-
const commentLength = chunk.readUint16LE(i + 32);
|
166
|
-
// Start of the actual content byte stream is after the 'local' record header,
|
167
|
-
// which is 30 bytes long plus filename and extra field
|
168
|
-
const start = chunk.readUint32LE(i + 42) + 30 + filenameLength + extraLength;
|
169
|
-
const end = start + compressedFileSize;
|
170
|
-
const filename = chunk.slice(i + 46, i + 46 + filenameLength).toString("utf-8");
|
171
|
-
const createRecordReadStream = () => {
|
172
|
-
const input = createReadStream(zipFile, { start, end });
|
173
|
-
if (compressionMethod === "deflate") {
|
174
|
-
const inflate = createInflateRaw();
|
175
|
-
input.pipe(inflate);
|
176
|
-
return inflate;
|
177
|
-
}
|
178
|
-
return input;
|
179
|
-
};
|
180
|
-
if (end > start) yield { path: filename, createReadStream: createRecordReadStream, compressionMethod };
|
181
|
-
// advance pointer to next central directory entry
|
182
|
-
i += 46 + filenameLength + extraLength + commentLength;
|
183
|
-
}
|
52
|
+
// Remove the unzipSubPath from the file name
|
53
|
+
entry.fileName = entry.fileName.substring(unzipSubPath.length);
|
54
|
+
}
|
55
|
+
|
56
|
+
const target = path.join(targetFolder, entry.fileName);
|
57
|
+
|
58
|
+
// Directory file names end with '/'.
|
59
|
+
// Note that entries for directories themselves are optional.
|
60
|
+
// An entry's fileName implicitly requires its parent directories to exist.
|
61
|
+
if (/[\/\\]$/.test(target)) {
|
62
|
+
await fsp.mkdir(target, { recursive: true });
|
63
|
+
|
64
|
+
zipfile.readEntry();
|
65
|
+
return;
|
66
|
+
}
|
67
|
+
|
68
|
+
// Skip existing files
|
69
|
+
if (await pathExists(target)) {
|
70
|
+
zipfile.readEntry();
|
71
|
+
return;
|
72
|
+
}
|
73
|
+
|
74
|
+
zipfile.openReadStream(entry, async (err, readStream) => {
|
75
|
+
if (err) {
|
76
|
+
reject(err);
|
77
|
+
return;
|
78
|
+
}
|
79
|
+
|
80
|
+
await pipeline(readStream, fs.createWriteStream(target));
|
81
|
+
|
82
|
+
zipfile.readEntry();
|
83
|
+
});
|
84
|
+
});
|
85
|
+
|
86
|
+
zipfile.once("end", function () {
|
87
|
+
zipfile.close();
|
88
|
+
resolve();
|
89
|
+
});
|
90
|
+
});
|
91
|
+
});
|
184
92
|
}
|
@@ -1,53 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
-
if (k2 === undefined) k2 = k;
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
-
}
|
8
|
-
Object.defineProperty(o, k2, desc);
|
9
|
-
}) : (function(o, m, k, k2) {
|
10
|
-
if (k2 === undefined) k2 = k;
|
11
|
-
o[k2] = m[k];
|
12
|
-
}));
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
15
|
-
}) : function(o, v) {
|
16
|
-
o["default"] = v;
|
17
|
-
});
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
19
|
-
if (mod && mod.__esModule) return mod;
|
20
|
-
var result = {};
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
22
|
-
__setModuleDefault(result, mod);
|
23
|
-
return result;
|
24
|
-
};
|
25
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
26
|
-
exports.getThemeSrcDirPath = void 0;
|
27
|
-
var path_1 = require("path");
|
28
|
-
var fs = __importStar(require("fs"));
|
29
|
-
var crawl_1 = require("./tools/crawl");
|
30
|
-
var exclude_1 = require("tsafe/exclude");
|
31
|
-
var reactProjectDirPath = process.cwd();
|
32
|
-
var themeSrcDirBasename = "keycloak-theme";
|
33
|
-
function getThemeSrcDirPath() {
|
34
|
-
var srcDirPath = (0, path_1.join)(reactProjectDirPath, "src");
|
35
|
-
var themeSrcDirPath = (0, crawl_1.crawl)(srcDirPath)
|
36
|
-
.map(function (fileRelativePath) {
|
37
|
-
var split = fileRelativePath.split(themeSrcDirBasename);
|
38
|
-
if (split.length !== 2) {
|
39
|
-
return undefined;
|
40
|
-
}
|
41
|
-
return (0, path_1.join)(srcDirPath, split[0] + themeSrcDirBasename);
|
42
|
-
})
|
43
|
-
.filter((0, exclude_1.exclude)(undefined))[0];
|
44
|
-
if (themeSrcDirPath === undefined) {
|
45
|
-
if (fs.existsSync((0, path_1.join)(srcDirPath, "login")) || fs.existsSync((0, path_1.join)(srcDirPath, "account"))) {
|
46
|
-
return { "themeSrcDirPath": srcDirPath };
|
47
|
-
}
|
48
|
-
return { "themeSrcDirPath": undefined };
|
49
|
-
}
|
50
|
-
return { themeSrcDirPath: themeSrcDirPath };
|
51
|
-
}
|
52
|
-
exports.getThemeSrcDirPath = getThemeSrcDirPath;
|
53
|
-
//# sourceMappingURL=getThemeSrcDirPath.js.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"getThemeSrcDirPath.js","sourceRoot":"","sources":["../src/bin/getThemeSrcDirPath.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6BAAwC;AACxC,qCAAyB;AACzB,uCAAsC;AACtC,yCAAwC;AAExC,IAAM,mBAAmB,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;AAE1C,IAAM,mBAAmB,GAAG,gBAAgB,CAAC;AAE7C,SAAgB,kBAAkB;IAC9B,IAAM,UAAU,GAAG,IAAA,WAAQ,EAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;IAExD,IAAM,eAAe,GAAuB,IAAA,aAAK,EAAC,UAAU,CAAC;SACxD,GAAG,CAAC,UAAA,gBAAgB;QACjB,IAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAE1D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;YACpB,OAAO,SAAS,CAAC;SACpB;QAED,OAAO,IAAA,WAAQ,EAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC;IAChE,CAAC,CAAC;SACD,MAAM,CAAC,IAAA,iBAAO,EAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEnC,IAAI,eAAe,KAAK,SAAS,EAAE;QAC/B,IAAI,EAAE,CAAC,UAAU,CAAC,IAAA,WAAQ,EAAC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAA,WAAQ,EAAC,UAAU,EAAE,SAAS,CAAC,CAAC,EAAE;YAChG,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,CAAC;SAC5C;QACD,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,CAAC;KAC3C;IAED,OAAO,EAAE,eAAe,iBAAA,EAAE,CAAC;AAC/B,CAAC;AAvBD,gDAuBC"}
|
@@ -1,33 +0,0 @@
|
|
1
|
-
import { join as pathJoin } from "path";
|
2
|
-
import * as fs from "fs";
|
3
|
-
import { crawl } from "./tools/crawl";
|
4
|
-
import { exclude } from "tsafe/exclude";
|
5
|
-
|
6
|
-
const reactProjectDirPath = process.cwd();
|
7
|
-
|
8
|
-
const themeSrcDirBasename = "keycloak-theme";
|
9
|
-
|
10
|
-
export function getThemeSrcDirPath() {
|
11
|
-
const srcDirPath = pathJoin(reactProjectDirPath, "src");
|
12
|
-
|
13
|
-
const themeSrcDirPath: string | undefined = crawl(srcDirPath)
|
14
|
-
.map(fileRelativePath => {
|
15
|
-
const split = fileRelativePath.split(themeSrcDirBasename);
|
16
|
-
|
17
|
-
if (split.length !== 2) {
|
18
|
-
return undefined;
|
19
|
-
}
|
20
|
-
|
21
|
-
return pathJoin(srcDirPath, split[0] + themeSrcDirBasename);
|
22
|
-
})
|
23
|
-
.filter(exclude(undefined))[0];
|
24
|
-
|
25
|
-
if (themeSrcDirPath === undefined) {
|
26
|
-
if (fs.existsSync(pathJoin(srcDirPath, "login")) || fs.existsSync(pathJoin(srcDirPath, "account"))) {
|
27
|
-
return { "themeSrcDirPath": srcDirPath };
|
28
|
-
}
|
29
|
-
return { "themeSrcDirPath": undefined };
|
30
|
-
}
|
31
|
-
|
32
|
-
return { themeSrcDirPath };
|
33
|
-
}
|