keycloakify 4.7.6 → 4.8.2
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/CHANGELOG.md +17 -0
- package/README.md +45 -11
- package/bin/build-keycloak-theme/build-keycloak-theme.d.ts +1 -0
- package/bin/build-keycloak-theme/build-keycloak-theme.js +13 -8
- package/bin/build-keycloak-theme/build-keycloak-theme.js.map +1 -1
- package/bin/build-keycloak-theme/generateJavaStackFiles.d.ts +1 -0
- package/bin/build-keycloak-theme/generateJavaStackFiles.js +27 -2
- package/bin/build-keycloak-theme/generateJavaStackFiles.js.map +1 -1
- package/bin/build-keycloak-theme/generateKeycloakThemeResources.d.ts +4 -1
- package/bin/build-keycloak-theme/generateKeycloakThemeResources.js +18 -1
- package/bin/build-keycloak-theme/generateKeycloakThemeResources.js.map +1 -1
- package/bin/create-keycloak-theme-email-directory.d.ts +2 -0
- package/bin/create-keycloak-theme-email-directory.js +94 -0
- package/bin/create-keycloak-theme-email-directory.js.map +1 -0
- package/bin/download-builtin-keycloak-theme.js +54 -13
- package/bin/download-builtin-keycloak-theme.js.map +1 -1
- package/bin/promptKeycloakVersion.d.ts +3 -0
- package/bin/promptKeycloakVersion.js +91 -0
- package/bin/promptKeycloakVersion.js.map +1 -0
- package/bin/tools/NpmModuleVersion.d.ts +22 -0
- package/bin/tools/NpmModuleVersion.js +103 -0
- package/bin/tools/NpmModuleVersion.js.map +1 -0
- package/bin/tools/createOctokit.d.ts +5 -0
- package/bin/tools/createOctokit.js +21 -0
- package/bin/tools/createOctokit.js.map +1 -0
- package/bin/tools/octokit-addons/getLatestsSemVersionedTag.d.ts +15 -0
- package/bin/tools/octokit-addons/getLatestsSemVersionedTag.js +112 -0
- package/bin/tools/octokit-addons/getLatestsSemVersionedTag.js.map +1 -0
- package/bin/tools/octokit-addons/listTags.d.ts +13 -0
- package/bin/tools/octokit-addons/listTags.js +154 -0
- package/bin/tools/octokit-addons/listTags.js.map +1 -0
- package/lib/i18n/KcLanguageTag.d.ts +1 -1
- package/lib/i18n/useKcLanguageTag.d.ts +1 -1
- package/package.json +31 -4
- package/src/bin/build-keycloak-theme/build-keycloak-theme.ts +13 -6
- package/src/bin/build-keycloak-theme/generateJavaStackFiles.ts +9 -3
- package/src/bin/build-keycloak-theme/generateKeycloakThemeResources.ts +27 -1
- package/src/bin/create-keycloak-theme-email-directory.ts +36 -0
- package/src/bin/download-builtin-keycloak-theme.ts +10 -15
- package/src/bin/promptKeycloakVersion.ts +44 -0
- package/src/bin/tools/NpmModuleVersion.ts +73 -0
- package/src/bin/tools/createOctokit.ts +7 -0
- package/src/bin/tools/octokit-addons/getLatestsSemVersionedTag.ts +40 -0
- package/src/bin/tools/octokit-addons/listTags.ts +49 -0
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "keycloakify",
|
3
|
-
"version": "4.
|
3
|
+
"version": "4.8.2",
|
4
4
|
"description": "Keycloak theme generator for Reacts app",
|
5
5
|
"repository": {
|
6
6
|
"type": "git",
|
@@ -10,6 +10,7 @@
|
|
10
10
|
"types": "lib/index.d.ts",
|
11
11
|
"bin": {
|
12
12
|
"build-keycloak-theme": "bin/build-keycloak-theme/index.js",
|
13
|
+
"create-keycloak-theme-email-directory": "bin/create-keycloak-theme-email-directory.js",
|
13
14
|
"download-builtin-keycloak-theme": "bin/download-builtin-keycloak-theme.js"
|
14
15
|
},
|
15
16
|
"lint-staged": {
|
@@ -35,14 +36,20 @@
|
|
35
36
|
"src/bin/build-keycloak-theme/generateStartKeycloakTestingContainer.ts",
|
36
37
|
"src/bin/build-keycloak-theme/index.ts",
|
37
38
|
"src/bin/build-keycloak-theme/replaceImportFromStatic.ts",
|
39
|
+
"src/bin/create-keycloak-theme-email-directory.ts",
|
38
40
|
"src/bin/download-builtin-keycloak-theme.ts",
|
39
41
|
"src/bin/generate-i18n-messages.ts",
|
40
42
|
"src/bin/link_in_test_app.ts",
|
43
|
+
"src/bin/promptKeycloakVersion.ts",
|
44
|
+
"src/bin/tools/NpmModuleVersion.ts",
|
41
45
|
"src/bin/tools/crawl.ts",
|
46
|
+
"src/bin/tools/createOctokit.ts",
|
42
47
|
"src/bin/tools/downloadAndUnzip.ts",
|
43
48
|
"src/bin/tools/getProjectRoot.ts",
|
44
49
|
"src/bin/tools/grant-exec-perms.ts",
|
45
50
|
"src/bin/tools/isInside.ts",
|
51
|
+
"src/bin/tools/octokit-addons/getLatestsSemVersionedTag.ts",
|
52
|
+
"src/bin/tools/octokit-addons/listTags.ts",
|
46
53
|
"src/bin/tools/rm.ts",
|
47
54
|
"src/bin/tools/transformCodebase.ts",
|
48
55
|
"src/lib/components/Error.tsx",
|
@@ -124,6 +131,9 @@
|
|
124
131
|
"bin/build-keycloak-theme/replaceImportFromStatic.d.ts",
|
125
132
|
"bin/build-keycloak-theme/replaceImportFromStatic.js",
|
126
133
|
"bin/build-keycloak-theme/replaceImportFromStatic.js.map",
|
134
|
+
"bin/create-keycloak-theme-email-directory.d.ts",
|
135
|
+
"bin/create-keycloak-theme-email-directory.js",
|
136
|
+
"bin/create-keycloak-theme-email-directory.js.map",
|
127
137
|
"bin/download-builtin-keycloak-theme.d.ts",
|
128
138
|
"bin/download-builtin-keycloak-theme.js",
|
129
139
|
"bin/download-builtin-keycloak-theme.js.map",
|
@@ -133,9 +143,18 @@
|
|
133
143
|
"bin/link_in_test_app.d.ts",
|
134
144
|
"bin/link_in_test_app.js",
|
135
145
|
"bin/link_in_test_app.js.map",
|
146
|
+
"bin/promptKeycloakVersion.d.ts",
|
147
|
+
"bin/promptKeycloakVersion.js",
|
148
|
+
"bin/promptKeycloakVersion.js.map",
|
149
|
+
"bin/tools/NpmModuleVersion.d.ts",
|
150
|
+
"bin/tools/NpmModuleVersion.js",
|
151
|
+
"bin/tools/NpmModuleVersion.js.map",
|
136
152
|
"bin/tools/crawl.d.ts",
|
137
153
|
"bin/tools/crawl.js",
|
138
154
|
"bin/tools/crawl.js.map",
|
155
|
+
"bin/tools/createOctokit.d.ts",
|
156
|
+
"bin/tools/createOctokit.js",
|
157
|
+
"bin/tools/createOctokit.js.map",
|
139
158
|
"bin/tools/downloadAndUnzip.d.ts",
|
140
159
|
"bin/tools/downloadAndUnzip.js",
|
141
160
|
"bin/tools/downloadAndUnzip.js.map",
|
@@ -148,6 +167,12 @@
|
|
148
167
|
"bin/tools/isInside.d.ts",
|
149
168
|
"bin/tools/isInside.js",
|
150
169
|
"bin/tools/isInside.js.map",
|
170
|
+
"bin/tools/octokit-addons/getLatestsSemVersionedTag.d.ts",
|
171
|
+
"bin/tools/octokit-addons/getLatestsSemVersionedTag.js",
|
172
|
+
"bin/tools/octokit-addons/getLatestsSemVersionedTag.js.map",
|
173
|
+
"bin/tools/octokit-addons/listTags.d.ts",
|
174
|
+
"bin/tools/octokit-addons/listTags.js",
|
175
|
+
"bin/tools/octokit-addons/listTags.js.map",
|
151
176
|
"bin/tools/rm.d.ts",
|
152
177
|
"bin/tools/rm.js",
|
153
178
|
"bin/tools/rm.js.map",
|
@@ -325,7 +350,7 @@
|
|
325
350
|
},
|
326
351
|
"devDependencies": {
|
327
352
|
"@emotion/react": "^11.4.1",
|
328
|
-
"@types/node": "^
|
353
|
+
"@types/node": "^17.0.25",
|
329
354
|
"@types/react": "^17.0.0",
|
330
355
|
"copyfiles": "^2.4.1",
|
331
356
|
"husky": "^4.3.8",
|
@@ -337,14 +362,16 @@
|
|
337
362
|
"typescript": "^4.2.3"
|
338
363
|
},
|
339
364
|
"dependencies": {
|
365
|
+
"@octokit/rest": "^18.12.0",
|
340
366
|
"cheerio": "^1.0.0-rc.5",
|
367
|
+
"cli-select": "^1.1.2",
|
341
368
|
"evt": "2.0.0-beta.39",
|
342
369
|
"minimal-polyfills": "^2.2.1",
|
343
370
|
"path-browserify": "^1.0.1",
|
371
|
+
"powerhooks": "^0.14.0",
|
344
372
|
"react-markdown": "^5.0.3",
|
345
373
|
"scripting-tools": "^0.19.13",
|
346
374
|
"tsafe": "^0.9.0",
|
347
|
-
"tss-react": "^3.5.2"
|
348
|
-
"powerhooks": "^0.14.0"
|
375
|
+
"tss-react": "^3.5.2"
|
349
376
|
}
|
350
377
|
}
|
@@ -19,6 +19,7 @@ const doUseExternalAssets = process.argv[2]?.toLowerCase() === "--external-asset
|
|
19
19
|
const parsedPackageJson: ParsedPackageJson = require(pathJoin(reactProjectDirPath, "package.json"));
|
20
20
|
|
21
21
|
export const keycloakThemeBuildingDirPath = pathJoin(reactProjectDirPath, "build_keycloak");
|
22
|
+
export const keycloakThemeEmailDirPath = pathJoin(keycloakThemeBuildingDirPath, "..", "keycloak_theme_email");
|
22
23
|
|
23
24
|
function sanitizeThemeName(name: string) {
|
24
25
|
return name
|
@@ -34,8 +35,9 @@ export function main() {
|
|
34
35
|
const extraThemeProperties: string[] = (parsedPackageJson as any)["keycloakify"]?.["extraThemeProperties"] ?? [];
|
35
36
|
const themeName = sanitizeThemeName(parsedPackageJson.name);
|
36
37
|
|
37
|
-
generateKeycloakThemeResources({
|
38
|
+
const { doBundleEmailTemplate } = generateKeycloakThemeResources({
|
38
39
|
keycloakThemeBuildingDirPath,
|
40
|
+
keycloakThemeEmailDirPath,
|
39
41
|
"reactAppBuildDirPath": pathJoin(reactProjectDirPath, "build"),
|
40
42
|
themeName,
|
41
43
|
...(() => {
|
@@ -78,21 +80,24 @@ export function main() {
|
|
78
80
|
});
|
79
81
|
|
80
82
|
const { jarFilePath } = generateJavaStackFiles({
|
81
|
-
version: parsedPackageJson.version,
|
83
|
+
"version": parsedPackageJson.version,
|
82
84
|
themeName,
|
83
|
-
homepage: parsedPackageJson.homepage,
|
85
|
+
"homepage": parsedPackageJson.homepage,
|
84
86
|
keycloakThemeBuildingDirPath,
|
87
|
+
doBundleEmailTemplate,
|
85
88
|
});
|
86
89
|
|
87
90
|
child_process.execSync("mvn package", {
|
88
91
|
"cwd": keycloakThemeBuildingDirPath,
|
89
92
|
});
|
90
93
|
|
94
|
+
//We want, however to test in a container running the latest Keycloak version
|
95
|
+
const containerKeycloakVersion = "18.0.0";
|
96
|
+
|
91
97
|
generateStartKeycloakTestingContainer({
|
92
98
|
keycloakThemeBuildingDirPath,
|
93
99
|
themeName,
|
94
|
-
|
95
|
-
"keycloakVersion": "17.0.1",
|
100
|
+
"keycloakVersion": containerKeycloakVersion,
|
96
101
|
});
|
97
102
|
|
98
103
|
console.log(
|
@@ -129,10 +134,12 @@ export function main() {
|
|
129
134
|
" value: -Dkeycloak.profile=preview",
|
130
135
|
"",
|
131
136
|
"",
|
132
|
-
|
137
|
+
`To test your theme locally you can spin up a Keycloak ${containerKeycloakVersion} container image with the theme pre loaded by running:`,
|
133
138
|
"",
|
134
139
|
`👉 $ ./${pathRelative(reactProjectDirPath, pathJoin(keycloakThemeBuildingDirPath, generateStartKeycloakTestingContainer.basename))} 👈`,
|
135
140
|
"",
|
141
|
+
"Test with different Keycloak versions by editing the .sh file. see available versions here: https://quay.io/repository/keycloak/keycloak?tab=tags",
|
142
|
+
"",
|
136
143
|
"Once your container is up and running: ",
|
137
144
|
"- Log into the admin console 👉 http://localhost:8080/admin username: admin, password: admin 👈",
|
138
145
|
'- Create a realm named "myrealm"',
|
@@ -2,10 +2,16 @@ import * as url from "url";
|
|
2
2
|
import * as fs from "fs";
|
3
3
|
import { join as pathJoin, dirname as pathDirname } from "path";
|
4
4
|
|
5
|
-
export function generateJavaStackFiles(params: {
|
5
|
+
export function generateJavaStackFiles(params: {
|
6
|
+
version: string;
|
7
|
+
themeName: string;
|
8
|
+
homepage?: string;
|
9
|
+
keycloakThemeBuildingDirPath: string;
|
10
|
+
doBundleEmailTemplate: boolean;
|
11
|
+
}): {
|
6
12
|
jarFilePath: string;
|
7
13
|
} {
|
8
|
-
const { themeName, version, homepage, keycloakThemeBuildingDirPath } = params;
|
14
|
+
const { themeName, version, homepage, keycloakThemeBuildingDirPath, doBundleEmailTemplate } = params;
|
9
15
|
|
10
16
|
{
|
11
17
|
const { pomFileCode } = (function generatePomFileCode(): {
|
@@ -63,7 +69,7 @@ export function generateJavaStackFiles(params: { version: string; themeName: str
|
|
63
69
|
"themes": [
|
64
70
|
{
|
65
71
|
"name": themeName,
|
66
|
-
"types": ["login"],
|
72
|
+
"types": ["login", ...(doBundleEmailTemplate ? ["email"] : [])],
|
67
73
|
},
|
68
74
|
],
|
69
75
|
},
|
@@ -12,17 +12,19 @@ export function generateKeycloakThemeResources(params: {
|
|
12
12
|
themeName: string;
|
13
13
|
reactAppBuildDirPath: string;
|
14
14
|
keycloakThemeBuildingDirPath: string;
|
15
|
+
keycloakThemeEmailDirPath: string;
|
15
16
|
urlPathname: string;
|
16
17
|
//If urlOrigin is not undefined then it means --externals-assets
|
17
18
|
urlOrigin: undefined | string;
|
18
19
|
extraPagesId: string[];
|
19
20
|
extraThemeProperties: string[];
|
20
21
|
keycloakVersion: string;
|
21
|
-
}) {
|
22
|
+
}): { doBundleEmailTemplate: boolean } {
|
22
23
|
const {
|
23
24
|
themeName,
|
24
25
|
reactAppBuildDirPath,
|
25
26
|
keycloakThemeBuildingDirPath,
|
27
|
+
keycloakThemeEmailDirPath,
|
26
28
|
urlPathname,
|
27
29
|
urlOrigin,
|
28
30
|
extraPagesId,
|
@@ -79,6 +81,28 @@ export function generateKeycloakThemeResources(params: {
|
|
79
81
|
},
|
80
82
|
});
|
81
83
|
|
84
|
+
let doBundleEmailTemplate: boolean;
|
85
|
+
|
86
|
+
email: {
|
87
|
+
if (!fs.existsSync(keycloakThemeEmailDirPath)) {
|
88
|
+
console.log(
|
89
|
+
[
|
90
|
+
`Not bundling email template because ${pathBasename(keycloakThemeEmailDirPath)} does not exist`,
|
91
|
+
`To start customizing the email template, run: 👉 npx create-keycloak-theme-email-directory 👈`,
|
92
|
+
].join("\n"),
|
93
|
+
);
|
94
|
+
doBundleEmailTemplate = false;
|
95
|
+
break email;
|
96
|
+
}
|
97
|
+
|
98
|
+
doBundleEmailTemplate = true;
|
99
|
+
|
100
|
+
transformCodebase({
|
101
|
+
"srcDirPath": keycloakThemeEmailDirPath,
|
102
|
+
"destDirPath": pathJoin(themeDirPath, "..", "email"),
|
103
|
+
});
|
104
|
+
}
|
105
|
+
|
82
106
|
const { generateFtlFilesCode } = generateFtlFilesCodeFactory({
|
83
107
|
"cssGlobalsToDefine": allCssGlobalsToDefine,
|
84
108
|
"indexHtmlCode": fs.readFileSync(pathJoin(reactAppBuildDirPath, "index.html")).toString("utf8"),
|
@@ -139,4 +163,6 @@ export function generateKeycloakThemeResources(params: {
|
|
139
163
|
pathJoin(themeDirPath, "theme.properties"),
|
140
164
|
Buffer.from("parent=keycloak".concat("\n\n", extraThemeProperties.join("\n\n")), "utf8"),
|
141
165
|
);
|
166
|
+
|
167
|
+
return { doBundleEmailTemplate };
|
142
168
|
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
|
3
|
+
import { downloadBuiltinKeycloakTheme } from "./download-builtin-keycloak-theme";
|
4
|
+
import { keycloakThemeEmailDirPath } from "./build-keycloak-theme";
|
5
|
+
import { join as pathJoin, basename as pathBasename } from "path";
|
6
|
+
import { transformCodebase } from "./tools/transformCodebase";
|
7
|
+
import { promptKeycloakVersion } from "./promptKeycloakVersion";
|
8
|
+
import * as fs from "fs";
|
9
|
+
|
10
|
+
if (require.main === module) {
|
11
|
+
(async () => {
|
12
|
+
if (fs.existsSync(keycloakThemeEmailDirPath)) {
|
13
|
+
console.log(`There is already a ./${pathBasename(keycloakThemeEmailDirPath)} directory in your project. Aborting.`);
|
14
|
+
|
15
|
+
process.exit(-1);
|
16
|
+
}
|
17
|
+
|
18
|
+
const { keycloakVersion } = await promptKeycloakVersion();
|
19
|
+
|
20
|
+
const builtinKeycloakThemeTmpDirPath = pathJoin(keycloakThemeEmailDirPath, "..", "tmp_xIdP3_builtin_keycloak_theme");
|
21
|
+
|
22
|
+
downloadBuiltinKeycloakTheme({
|
23
|
+
keycloakVersion,
|
24
|
+
"destDirPath": builtinKeycloakThemeTmpDirPath,
|
25
|
+
});
|
26
|
+
|
27
|
+
transformCodebase({
|
28
|
+
"srcDirPath": pathJoin(builtinKeycloakThemeTmpDirPath, "base", "email"),
|
29
|
+
"destDirPath": keycloakThemeEmailDirPath,
|
30
|
+
});
|
31
|
+
|
32
|
+
console.log(`./${pathBasename(keycloakThemeEmailDirPath)} ready to be customized`);
|
33
|
+
|
34
|
+
fs.rmSync(builtinKeycloakThemeTmpDirPath, { "recursive": true, "force": true });
|
35
|
+
})();
|
36
|
+
}
|
@@ -3,6 +3,7 @@
|
|
3
3
|
import { keycloakThemeBuildingDirPath } from "./build-keycloak-theme";
|
4
4
|
import { join as pathJoin } from "path";
|
5
5
|
import { downloadAndUnzip } from "./tools/downloadAndUnzip";
|
6
|
+
import { promptKeycloakVersion } from "./promptKeycloakVersion";
|
6
7
|
|
7
8
|
export function downloadBuiltinKeycloakTheme(params: { keycloakVersion: string; destDirPath: string }) {
|
8
9
|
const { keycloakVersion, destDirPath } = params;
|
@@ -17,22 +18,16 @@ export function downloadBuiltinKeycloakTheme(params: { keycloakVersion: string;
|
|
17
18
|
}
|
18
19
|
|
19
20
|
if (require.main === module) {
|
20
|
-
|
21
|
-
const keycloakVersion =
|
21
|
+
(async () => {
|
22
|
+
const { keycloakVersion } = await promptKeycloakVersion();
|
22
23
|
|
23
|
-
|
24
|
-
return "11.0.3";
|
25
|
-
}
|
24
|
+
const destDirPath = pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources", "theme");
|
26
25
|
|
27
|
-
|
28
|
-
})();
|
29
|
-
|
30
|
-
const destDirPath = pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources", "theme");
|
31
|
-
|
32
|
-
console.log(`Downloading builtins theme of Keycloak ${keycloakVersion} here ${destDirPath}`);
|
26
|
+
console.log(`Downloading builtins theme of Keycloak ${keycloakVersion} here ${destDirPath}`);
|
33
27
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
28
|
+
downloadBuiltinKeycloakTheme({
|
29
|
+
keycloakVersion,
|
30
|
+
destDirPath,
|
31
|
+
});
|
32
|
+
})();
|
38
33
|
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import { getLatestsSemVersionedTagFactory } from "./tools/octokit-addons/getLatestsSemVersionedTag";
|
2
|
+
import { Octokit } from "@octokit/rest";
|
3
|
+
import cliSelect from "cli-select";
|
4
|
+
|
5
|
+
export async function promptKeycloakVersion() {
|
6
|
+
const { getLatestsSemVersionedTag } = (() => {
|
7
|
+
const { octokit } = (() => {
|
8
|
+
const githubToken = process.env.GITHUB_TOKEN;
|
9
|
+
|
10
|
+
const octokit = new Octokit(githubToken === undefined ? undefined : { "auth": githubToken });
|
11
|
+
|
12
|
+
return { octokit };
|
13
|
+
})();
|
14
|
+
|
15
|
+
const { getLatestsSemVersionedTag } = getLatestsSemVersionedTagFactory({ octokit });
|
16
|
+
|
17
|
+
return { getLatestsSemVersionedTag };
|
18
|
+
})();
|
19
|
+
|
20
|
+
console.log("Initialize the directory with email template from which keycloak version?");
|
21
|
+
|
22
|
+
const tags = await getLatestsSemVersionedTag({
|
23
|
+
"count": 15,
|
24
|
+
"doIgnoreBeta": true,
|
25
|
+
"owner": "keycloak",
|
26
|
+
"repo": "keycloak",
|
27
|
+
}).then(arr => arr.map(({ tag }) => tag));
|
28
|
+
|
29
|
+
if (process.env["GITHUB_ACTIONS"] === "true") {
|
30
|
+
return { "keycloakVersion": tags[0] };
|
31
|
+
}
|
32
|
+
|
33
|
+
const { value: keycloakVersion } = await cliSelect<string>({
|
34
|
+
"values": tags,
|
35
|
+
}).catch(() => {
|
36
|
+
console.log("Aborting");
|
37
|
+
|
38
|
+
process.exit(-1);
|
39
|
+
});
|
40
|
+
|
41
|
+
console.log(keycloakVersion);
|
42
|
+
|
43
|
+
return { keycloakVersion };
|
44
|
+
}
|
@@ -0,0 +1,73 @@
|
|
1
|
+
export type NpmModuleVersion = {
|
2
|
+
major: number;
|
3
|
+
minor: number;
|
4
|
+
patch: number;
|
5
|
+
betaPreRelease?: number;
|
6
|
+
};
|
7
|
+
|
8
|
+
export namespace NpmModuleVersion {
|
9
|
+
export function parse(versionStr: string): NpmModuleVersion {
|
10
|
+
const match = versionStr.match(/^([0-9]+)\.([0-9]+)\.([0-9]+)(?:-beta.([0-9]+))?/);
|
11
|
+
|
12
|
+
if (!match) {
|
13
|
+
throw new Error(`${versionStr} is not a valid NPM version`);
|
14
|
+
}
|
15
|
+
|
16
|
+
return {
|
17
|
+
"major": parseInt(match[1]),
|
18
|
+
"minor": parseInt(match[2]),
|
19
|
+
"patch": parseInt(match[3]),
|
20
|
+
...(() => {
|
21
|
+
const str = match[4];
|
22
|
+
return str === undefined ? {} : { "betaPreRelease": parseInt(str) };
|
23
|
+
})(),
|
24
|
+
};
|
25
|
+
}
|
26
|
+
|
27
|
+
export function stringify(v: NpmModuleVersion) {
|
28
|
+
return `${v.major}.${v.minor}.${v.patch}${v.betaPreRelease === undefined ? "" : `-beta.${v.betaPreRelease}`}`;
|
29
|
+
}
|
30
|
+
|
31
|
+
/**
|
32
|
+
*
|
33
|
+
* v1 < v2 => -1
|
34
|
+
* v1 === v2 => 0
|
35
|
+
* v1 > v2 => 1
|
36
|
+
*
|
37
|
+
*/
|
38
|
+
export function compare(v1: NpmModuleVersion, v2: NpmModuleVersion): -1 | 0 | 1 {
|
39
|
+
const sign = (diff: number): -1 | 0 | 1 => (diff === 0 ? 0 : diff < 0 ? -1 : 1);
|
40
|
+
const noUndefined = (n: number | undefined) => n ?? Infinity;
|
41
|
+
|
42
|
+
for (const level of ["major", "minor", "patch", "betaPreRelease"] as const) {
|
43
|
+
if (noUndefined(v1[level]) !== noUndefined(v2[level])) {
|
44
|
+
return sign(noUndefined(v1[level]) - noUndefined(v2[level]));
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
return 0;
|
49
|
+
}
|
50
|
+
|
51
|
+
/*
|
52
|
+
console.log(compare(parse("3.0.0-beta.3"), parse("3.0.0")) === -1 )
|
53
|
+
console.log(compare(parse("3.0.0-beta.3"), parse("3.0.0-beta.4")) === -1 )
|
54
|
+
console.log(compare(parse("3.0.0-beta.3"), parse("4.0.0")) === -1 )
|
55
|
+
*/
|
56
|
+
|
57
|
+
export function bumpType(params: { versionBehindStr: string; versionAheadStr: string }): "major" | "minor" | "patch" | "betaPreRelease" | "same" {
|
58
|
+
const versionAhead = parse(params.versionAheadStr);
|
59
|
+
const versionBehind = parse(params.versionBehindStr);
|
60
|
+
|
61
|
+
if (compare(versionBehind, versionAhead) === 1) {
|
62
|
+
throw new Error(`Version regression ${versionBehind} -> ${versionAhead}`);
|
63
|
+
}
|
64
|
+
|
65
|
+
for (const level of ["major", "minor", "patch", "betaPreRelease"] as const) {
|
66
|
+
if (versionBehind[level] !== versionAhead[level]) {
|
67
|
+
return level;
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
return "same";
|
72
|
+
}
|
73
|
+
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import { listTagsFactory } from "./listTags";
|
2
|
+
import type { Octokit } from "@octokit/rest";
|
3
|
+
import { NpmModuleVersion } from "../NpmModuleVersion";
|
4
|
+
|
5
|
+
export function getLatestsSemVersionedTagFactory(params: { octokit: Octokit }) {
|
6
|
+
const { octokit } = params;
|
7
|
+
|
8
|
+
async function getLatestsSemVersionedTag(params: { owner: string; repo: string; doIgnoreBeta: boolean; count: number }): Promise<
|
9
|
+
{
|
10
|
+
tag: string;
|
11
|
+
version: NpmModuleVersion;
|
12
|
+
}[]
|
13
|
+
> {
|
14
|
+
const { owner, repo, doIgnoreBeta, count } = params;
|
15
|
+
|
16
|
+
const semVersionedTags: { tag: string; version: NpmModuleVersion }[] = [];
|
17
|
+
|
18
|
+
const { listTags } = listTagsFactory({ octokit });
|
19
|
+
|
20
|
+
for await (const tag of listTags({ owner, repo })) {
|
21
|
+
let version: NpmModuleVersion;
|
22
|
+
|
23
|
+
try {
|
24
|
+
version = NpmModuleVersion.parse(tag.replace(/^[vV]?/, ""));
|
25
|
+
} catch {
|
26
|
+
continue;
|
27
|
+
}
|
28
|
+
|
29
|
+
if (doIgnoreBeta && version.betaPreRelease !== undefined) {
|
30
|
+
continue;
|
31
|
+
}
|
32
|
+
|
33
|
+
semVersionedTags.push({ tag, version });
|
34
|
+
}
|
35
|
+
|
36
|
+
return semVersionedTags.sort(({ version: vX }, { version: vY }) => NpmModuleVersion.compare(vY, vX)).slice(0, count);
|
37
|
+
}
|
38
|
+
|
39
|
+
return { getLatestsSemVersionedTag };
|
40
|
+
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
import type { Octokit } from "@octokit/rest";
|
2
|
+
|
3
|
+
const per_page = 99;
|
4
|
+
|
5
|
+
export function listTagsFactory(params: { octokit: Octokit }) {
|
6
|
+
const { octokit } = params;
|
7
|
+
|
8
|
+
const octokit_repo_listTags = async (params: { owner: string; repo: string; per_page: number; page: number }) => {
|
9
|
+
return octokit.repos.listTags(params);
|
10
|
+
};
|
11
|
+
|
12
|
+
async function* listTags(params: { owner: string; repo: string }): AsyncGenerator<string> {
|
13
|
+
const { owner, repo } = params;
|
14
|
+
|
15
|
+
let page = 1;
|
16
|
+
|
17
|
+
while (true) {
|
18
|
+
const resp = await octokit_repo_listTags({
|
19
|
+
owner,
|
20
|
+
repo,
|
21
|
+
per_page,
|
22
|
+
"page": page++,
|
23
|
+
});
|
24
|
+
|
25
|
+
for (const branch of resp.data.map(({ name }) => name)) {
|
26
|
+
yield branch;
|
27
|
+
}
|
28
|
+
|
29
|
+
if (resp.data.length < 99) {
|
30
|
+
break;
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
/** Returns the same "latest" tag as deno.land/x, not actually the latest though */
|
36
|
+
async function getLatestTag(params: { owner: string; repo: string }): Promise<string | undefined> {
|
37
|
+
const { owner, repo } = params;
|
38
|
+
|
39
|
+
const itRes = await listTags({ owner, repo }).next();
|
40
|
+
|
41
|
+
if (itRes.done) {
|
42
|
+
return undefined;
|
43
|
+
}
|
44
|
+
|
45
|
+
return itRes.value;
|
46
|
+
}
|
47
|
+
|
48
|
+
return { listTags, getLatestTag };
|
49
|
+
}
|