keycloakify 6.10.1 → 6.11.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.
Files changed (39) hide show
  1. package/README.md +6 -0
  2. package/bin/keycloakify/BuildOptions.d.ts +5 -0
  3. package/bin/keycloakify/BuildOptions.js +47 -8
  4. package/bin/keycloakify/BuildOptions.js.map +1 -1
  5. package/bin/keycloakify/generateJavaStackFiles.d.ts +2 -1
  6. package/bin/keycloakify/generateJavaStackFiles.js +4 -5
  7. package/bin/keycloakify/generateJavaStackFiles.js.map +1 -1
  8. package/bin/keycloakify/keycloakify.js +39 -8
  9. package/bin/keycloakify/keycloakify.js.map +1 -1
  10. package/bin/tools/crc32.d.ts +9 -0
  11. package/bin/tools/crc32.js +63 -0
  12. package/bin/tools/crc32.js.map +1 -0
  13. package/bin/tools/deflate.d.ts +24 -0
  14. package/bin/tools/deflate.js +155 -0
  15. package/bin/tools/deflate.js.map +1 -0
  16. package/bin/tools/jar.d.ts +14 -0
  17. package/bin/tools/jar.js +124 -0
  18. package/bin/tools/jar.js.map +1 -0
  19. package/bin/tools/tee.d.ts +3 -0
  20. package/bin/tools/tee.js +36 -0
  21. package/bin/tools/tee.js.map +1 -0
  22. package/bin/tools/walk.d.ts +8 -0
  23. package/bin/tools/walk.js +125 -0
  24. package/bin/tools/walk.js.map +1 -0
  25. package/bin/tools/zip.d.ts +29 -0
  26. package/bin/tools/zip.js +329 -0
  27. package/bin/tools/zip.js.map +1 -0
  28. package/bin/tsconfig.tsbuildinfo +1 -1
  29. package/package.json +25 -1
  30. package/src/bin/keycloakify/BuildOptions.ts +31 -4
  31. package/src/bin/keycloakify/generateJavaStackFiles.ts +6 -8
  32. package/src/bin/keycloakify/keycloakify.ts +25 -5
  33. package/src/bin/tools/crc32.ts +54 -0
  34. package/src/bin/tools/deflate.ts +61 -0
  35. package/src/bin/tools/downloadAndUnzip.ts +1 -1
  36. package/src/bin/tools/jar.ts +100 -0
  37. package/src/bin/tools/tee.ts +37 -0
  38. package/src/bin/tools/walk.ts +19 -0
  39. package/src/bin/tools/zip.ts +245 -0
@@ -0,0 +1,245 @@
1
+ import { Transform, TransformOptions } from "stream";
2
+ import { createReadStream } from "fs";
3
+ import { stat } from "fs/promises";
4
+
5
+ import { deflateBuffer, deflateStream } from "./deflate";
6
+
7
+ /**
8
+ * Zip source
9
+ * @property filename the name of the entry in the archie
10
+ * @property path of the source file, if the source is an actual file
11
+ * @property data the actual data buffer, if the source is constructed in-memory
12
+ */
13
+ export type ZipSource = { path: string } & ({ fsPath: string } | { data: Buffer });
14
+
15
+ export type ZipRecord = {
16
+ path: string;
17
+ compression: "deflate" | undefined;
18
+ uncompressedSize: number;
19
+ compressedSize?: number;
20
+ crc32?: number;
21
+ offset?: number;
22
+ };
23
+
24
+ /**
25
+ * @returns the actual byte size of an string
26
+ */
27
+ function utf8size(s: string) {
28
+ return new Blob([s]).size;
29
+ }
30
+
31
+ /**
32
+ * @param record
33
+ * @returns a buffer representing a Zip local header
34
+ * @link https://en.wikipedia.org/wiki/ZIP_(file_format)#Local_file_header
35
+ */
36
+ function localHeader(record: ZipRecord) {
37
+ const { path, compression, uncompressedSize } = record;
38
+ const filenameSize = utf8size(path);
39
+ const buf = Buffer.alloc(30 + filenameSize);
40
+
41
+ buf.writeUInt32LE(0x04_03_4b_50, 0); // local header signature
42
+ buf.writeUInt16LE(10, 4); // min version
43
+ // we write 0x08 because crc and compressed size are unknown at
44
+ buf.writeUInt16LE(0x08, 6); // general purpose bit flag
45
+ buf.writeUInt16LE(compression ? ({ "deflate": 8 } as const)[compression] : 0, 8);
46
+ buf.writeUInt16LE(0, 10); // modified time
47
+ buf.writeUInt16LE(0, 12); // modified date
48
+ buf.writeUInt32LE(0, 14); // crc unknown
49
+ buf.writeUInt32LE(0, 18); // compressed size unknown
50
+ buf.writeUInt32LE(uncompressedSize, 22);
51
+ buf.writeUInt16LE(filenameSize, 26);
52
+ buf.writeUInt16LE(0, 28); // extra field length
53
+ buf.write(path, 30, "utf-8");
54
+
55
+ return buf;
56
+ }
57
+
58
+ /**
59
+ * @param record
60
+ * @returns a buffer representing a Zip central header
61
+ * @link https://en.wikipedia.org/wiki/ZIP_(file_format)#Central_directory_file_header
62
+ */
63
+ function centralHeader(record: ZipRecord) {
64
+ const { path, compression, crc32, compressedSize, uncompressedSize, offset } = record;
65
+ const filenameSize = utf8size(path);
66
+ const buf = Buffer.alloc(46 + filenameSize);
67
+ const isFile = !path.endsWith("/");
68
+
69
+ if (typeof offset === "undefined") throw new Error("Illegal argument");
70
+
71
+ // we don't want to deal with possibly messed up file or directory
72
+ // permissions, so we ignore the original permissions
73
+ const externalAttr = isFile ? 0x81a40000 : 0x41ed0000;
74
+
75
+ buf.writeUInt32LE(0x0201_4b50, 0); // central header signature
76
+ buf.writeUInt16LE(10, 4); // version
77
+ buf.writeUInt16LE(10, 6); // min version
78
+ buf.writeUInt16LE(0, 8); // general purpose bit flag
79
+ buf.writeUInt16LE(compression ? ({ "deflate": 8 } as const)[compression] : 0, 10);
80
+ buf.writeUInt16LE(0, 12); // modified time
81
+ buf.writeUInt16LE(0, 14); // modified date
82
+ buf.writeUInt32LE(crc32 || 0, 16);
83
+ buf.writeUInt32LE(compressedSize || 0, 20);
84
+ buf.writeUInt32LE(uncompressedSize, 24);
85
+ buf.writeUInt16LE(filenameSize, 28);
86
+ buf.writeUInt16LE(0, 30); // extra field length
87
+ buf.writeUInt16LE(0, 32); // comment field length
88
+ buf.writeUInt16LE(0, 34); // disk number
89
+ buf.writeUInt16LE(0, 36); // internal
90
+ buf.writeUInt32LE(externalAttr, 38); // external
91
+ buf.writeUInt32LE(offset, 42); // offset where file starts
92
+ buf.write(path, 46, "utf-8");
93
+
94
+ return buf;
95
+ }
96
+
97
+ /**
98
+ * @returns a buffer representing an Zip End-Of-Central-Directory block
99
+ * @link https://en.wikipedia.org/wiki/ZIP_(file_format)#End_of_central_directory_record_(EOCD)
100
+ */
101
+ function eocd({ offset, cdSize, nRecords }: { offset: number; cdSize: number; nRecords: number }) {
102
+ const buf = Buffer.alloc(22);
103
+ buf.writeUint32LE(0x06054b50, 0); // eocd signature
104
+ buf.writeUInt16LE(0, 4); // disc number
105
+ buf.writeUint16LE(0, 6); // disc where central directory starts
106
+ buf.writeUint16LE(nRecords, 8); // records on this disc
107
+ buf.writeUInt16LE(nRecords, 10); // records total
108
+ buf.writeUInt32LE(cdSize, 12); // byte size of cd
109
+ buf.writeUInt32LE(offset, 16); // cd offset
110
+ buf.writeUint16LE(0, 20); // comment length
111
+
112
+ return buf;
113
+ }
114
+
115
+ /**
116
+ * @returns a stream Transform, which reads a stream of ZipRecords and
117
+ * writes a bytestream
118
+ */
119
+ export default function zip() {
120
+ /**
121
+ * This is called when the input stream of ZipSource items is finished.
122
+ * Will write central directory and end-of-central-direcotry blocks.
123
+ */
124
+ const final = () => {
125
+ // write central directory
126
+ let cdSize = 0;
127
+ for (const record of records) {
128
+ const head = centralHeader(record);
129
+ zipTransform.push(head);
130
+ cdSize += head.length;
131
+ }
132
+
133
+ // write end-of-central-directory
134
+ zipTransform.push(eocd({ offset, cdSize, nRecords: records.length }));
135
+ // signal stream end
136
+ zipTransform.push(null);
137
+ };
138
+
139
+ /**
140
+ * Write a directory entry to the archive
141
+ * @param path
142
+ */
143
+ const writeDir = async (path: string) => {
144
+ const record: ZipRecord = {
145
+ path: path + "/",
146
+ offset,
147
+ compression: undefined,
148
+ uncompressedSize: 0
149
+ };
150
+ const head = localHeader(record);
151
+ zipTransform.push(head);
152
+ records.push(record);
153
+ offset += head.length;
154
+ };
155
+
156
+ /**
157
+ * Write a file entry to the archive
158
+ * @param archivePath path of the file in archive
159
+ * @param fsPath path to file on filesystem
160
+ * @param size of the actual, uncompressed, file
161
+ */
162
+ const writeFile = async (archivePath: string, fsPath: string, size: number) => {
163
+ const record: ZipRecord = {
164
+ path: archivePath,
165
+ offset,
166
+ compression: "deflate",
167
+ uncompressedSize: size
168
+ };
169
+ const head = localHeader(record);
170
+ zipTransform.push(head);
171
+
172
+ const { crc32, compressedSize } = await deflateStream(createReadStream(fsPath), chunk => zipTransform.push(chunk));
173
+
174
+ record.crc32 = crc32;
175
+ record.compressedSize = compressedSize;
176
+ records.push(record);
177
+ offset += head.length + compressedSize;
178
+ };
179
+
180
+ /**
181
+ * Write archive record based on filesystem file or directory
182
+ * @param archivePath path of item in archive
183
+ * @param fsPath path to item on filesystem
184
+ */
185
+ const writeFromPath = async (archivePath: string, fsPath: string) => {
186
+ const fileStats = await stat(fsPath);
187
+ fileStats.isDirectory() ? await writeDir(archivePath) /**/ : await writeFile(archivePath, fsPath, fileStats.size) /**/;
188
+ };
189
+
190
+ /**
191
+ * Write archive record based on data in a buffer
192
+ * @param path
193
+ * @param data
194
+ */
195
+ const writeFromBuffer = async (path: string, data: Buffer) => {
196
+ const { deflated, crc32 } = await deflateBuffer(data);
197
+ const record: ZipRecord = {
198
+ path,
199
+ compression: "deflate",
200
+ crc32,
201
+ uncompressedSize: data.length,
202
+ compressedSize: deflated.length,
203
+ offset
204
+ };
205
+ const head = localHeader(record);
206
+ zipTransform.push(head);
207
+ zipTransform.push(deflated);
208
+ records.push(record);
209
+ offset += head.length + deflated.length;
210
+ };
211
+
212
+ /**
213
+ * Write an archive record
214
+ * @param source
215
+ */
216
+ const writeRecord = async (source: ZipSource) => {
217
+ if ("fsPath" in source) await writeFromPath(source.path, source.fsPath);
218
+ else if ("data" in source) await writeFromBuffer(source.path, source.data);
219
+ else throw new Error("Illegal argument " + typeof source + " " + source);
220
+ };
221
+
222
+ /**
223
+ * The actual stream transform function
224
+ * @param source
225
+ * @param _ encoding, ignored
226
+ * @param cb
227
+ */
228
+ const transform: TransformOptions["transform"] = async (source: ZipSource, _, cb) => {
229
+ await writeRecord(source);
230
+ cb();
231
+ };
232
+
233
+ /** offset and records keep local state during processing */
234
+ let offset = 0;
235
+ const records: ZipRecord[] = [];
236
+
237
+ const zipTransform = new Transform({
238
+ readableObjectMode: false,
239
+ writableObjectMode: true,
240
+ transform,
241
+ final
242
+ });
243
+
244
+ return zipTransform;
245
+ }