semantic-release-minecraft 1.1.2 → 1.2.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/CHANGELOG.md +12 -0
- package/dist/curseforge.d.ts +2 -2
- package/dist/curseforge.d.ts.map +1 -1
- package/dist/curseforge.js +47 -115
- package/dist/curseforge.js.map +1 -1
- package/dist/definitions/curseforge.d.ts +6 -6
- package/dist/definitions/{plugin_config.d.ts → plugin-config.d.ts} +4 -3
- package/dist/definitions/plugin-config.d.ts.map +1 -0
- package/dist/definitions/plugin-config.js +2 -0
- package/dist/definitions/plugin-config.js.map +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -23
- package/dist/index.js.map +1 -1
- package/dist/modrinth.d.ts +3 -3
- package/dist/modrinth.d.ts.map +1 -1
- package/dist/modrinth.js +58 -223
- package/dist/modrinth.js.map +1 -1
- package/dist/prepare.d.ts +4 -8
- package/dist/prepare.d.ts.map +1 -1
- package/dist/prepare.js +31 -32
- package/dist/prepare.js.map +1 -1
- package/dist/utils/glob-utils.d.ts +6 -0
- package/dist/utils/glob-utils.d.ts.map +1 -0
- package/dist/utils/glob-utils.js +27 -0
- package/dist/utils/glob-utils.js.map +1 -0
- package/dist/utils/platform/curseforge-utils.d.ts +4 -0
- package/dist/utils/platform/curseforge-utils.d.ts.map +1 -0
- package/dist/utils/platform/curseforge-utils.js +7 -0
- package/dist/utils/platform/curseforge-utils.js.map +1 -0
- package/dist/utils/platform/utils.d.ts +10 -0
- package/dist/utils/platform/utils.d.ts.map +1 -0
- package/dist/utils/platform/utils.js +56 -0
- package/dist/utils/platform/utils.js.map +1 -0
- package/dist/utils/template-utils.d.ts +26 -0
- package/dist/utils/template-utils.d.ts.map +1 -0
- package/dist/utils/template-utils.js +40 -0
- package/dist/utils/template-utils.js.map +1 -0
- package/dist/utils/utils.d.ts +4 -26
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +5 -79
- package/dist/utils/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/curseforge.ts +98 -160
- package/src/definitions/curseforge.ts +6 -6
- package/src/definitions/plugin-config.ts +68 -0
- package/src/index.ts +28 -34
- package/src/modrinth.ts +78 -271
- package/src/prepare.ts +43 -52
- package/src/utils/glob-utils.ts +38 -0
- package/src/utils/platform/curseforge-utils.ts +17 -0
- package/src/utils/platform/utils.ts +84 -0
- package/src/utils/template-utils.ts +54 -0
- package/src/utils/utils.ts +5 -115
- package/dist/definitions/plugin_config.d.ts.map +0 -1
- package/dist/definitions/plugin_config.js +0 -2
- package/dist/definitions/plugin_config.js.map +0 -1
- package/src/definitions/plugin_config.ts +0 -68
package/src/prepare.ts
CHANGED
|
@@ -1,37 +1,38 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
|
-
import {
|
|
2
|
+
import { PrepareContext } from 'semantic-release';
|
|
3
3
|
import {
|
|
4
4
|
BUKKIT_GAME_VERSION_TYPE,
|
|
5
5
|
CurseForgeGameVersion,
|
|
6
6
|
CurseForgeGameVersionMap,
|
|
7
7
|
CurseForgeGameVersionType,
|
|
8
8
|
} from './definitions/curseforge.js';
|
|
9
|
-
import {
|
|
10
|
-
import { getCurseForgeModLoaders
|
|
9
|
+
import { PluginConfig } from './definitions/plugin-config';
|
|
10
|
+
import { getCurseForgeModLoaders } from './utils/platform/curseforge-utils';
|
|
11
|
+
import { toArray } from './utils/utils.js';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
|
-
*
|
|
14
|
+
* Get CurseForge game version IDs based on the plugin configuration.
|
|
14
15
|
*/
|
|
15
16
|
export async function getCurseForgeGameVersionIds(
|
|
16
17
|
apiToken: string,
|
|
17
|
-
pluginConfig:
|
|
18
|
-
|
|
19
|
-
nextRelease: NextRelease
|
|
18
|
+
pluginConfig: PluginConfig,
|
|
19
|
+
context: PrepareContext
|
|
20
20
|
): Promise<number[]> {
|
|
21
|
+
const { nextRelease } = context;
|
|
22
|
+
|
|
21
23
|
const curseforgeConfig = pluginConfig.curseforge!;
|
|
22
24
|
|
|
23
|
-
const modLoaders = getCurseForgeModLoaders(pluginConfig,
|
|
24
|
-
|
|
25
|
+
const modLoaders = getCurseForgeModLoaders(pluginConfig, nextRelease);
|
|
26
|
+
|
|
27
|
+
const javaVersions = toArray(curseforgeConfig.java_versions);
|
|
25
28
|
const gameVersions = toArray(
|
|
26
|
-
curseforgeConfig.game_versions || pluginConfig.game_versions
|
|
29
|
+
curseforgeConfig.game_versions || pluginConfig.game_versions
|
|
27
30
|
);
|
|
28
31
|
const pluginGameVersions = toArray(
|
|
29
|
-
curseforgeConfig.game_versions_for_plugins
|
|
30
|
-
);
|
|
31
|
-
const addonGameVersions = toArray(
|
|
32
|
-
curseforgeConfig.game_versions_for_addon || []
|
|
32
|
+
curseforgeConfig.game_versions_for_plugins
|
|
33
33
|
);
|
|
34
|
-
const
|
|
34
|
+
const addonGameVersions = toArray(curseforgeConfig.game_versions_for_addon);
|
|
35
|
+
const environments = toArray(curseforgeConfig.environments);
|
|
35
36
|
|
|
36
37
|
const map = await createCurseForgeGameVersionMap(apiToken);
|
|
37
38
|
|
|
@@ -42,12 +43,9 @@ export async function getCurseForgeGameVersionIds(
|
|
|
42
43
|
// TODO: Modrinth 和 CurseForge 的游戏版本命名格式转化,以 Modrinth 为基准
|
|
43
44
|
// const gameVersionNames = gameVersions.map(x => formatCurseForgeGameVersionSnapshot(x));
|
|
44
45
|
|
|
45
|
-
// 模组的游戏版本名称
|
|
46
46
|
const gameVersionIds = findCurseForgeGameVersionIdsByNames(
|
|
47
47
|
map.game_versions,
|
|
48
|
-
gameVersions
|
|
49
|
-
undefined,
|
|
50
|
-
CURSEFORGE_GAME_VERSION_SNAPSHOT_NAME_COMPARER
|
|
48
|
+
gameVersions
|
|
51
49
|
);
|
|
52
50
|
|
|
53
51
|
const loaderIds = findCurseForgeGameVersionIdsByNames(
|
|
@@ -60,13 +58,11 @@ export async function getCurseForgeGameVersionIds(
|
|
|
60
58
|
javaVersionNames
|
|
61
59
|
);
|
|
62
60
|
|
|
63
|
-
// 插件的游戏版本名称
|
|
64
61
|
const pluginGameVersionIds = findCurseForgeGameVersionIdsByNames(
|
|
65
62
|
map.game_versions_for_plugins,
|
|
66
63
|
pluginGameVersions
|
|
67
64
|
);
|
|
68
65
|
|
|
69
|
-
// 附加组件的游戏版本名称
|
|
70
66
|
const addonGameVersionIds = findCurseForgeGameVersionIdsByNames(
|
|
71
67
|
map.game_versions_for_addons,
|
|
72
68
|
addonGameVersions
|
|
@@ -89,7 +85,9 @@ export async function getCurseForgeGameVersionIds(
|
|
|
89
85
|
return curseforgeGameVersionIds;
|
|
90
86
|
}
|
|
91
87
|
|
|
92
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Create a CurseForge game version map by categorizing game versions based on their type names.
|
|
90
|
+
*/
|
|
93
91
|
async function createCurseForgeGameVersionMap(
|
|
94
92
|
apiToken: string
|
|
95
93
|
): Promise<CurseForgeGameVersionMap> {
|
|
@@ -120,18 +118,9 @@ async function createCurseForgeGameVersionMap(
|
|
|
120
118
|
};
|
|
121
119
|
}
|
|
122
120
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
typeName: string
|
|
127
|
-
): CurseForgeGameVersion[] {
|
|
128
|
-
const filteredTypes = types.filter((x) => x.slug.startsWith(typeName));
|
|
129
|
-
return versions.filter((v) =>
|
|
130
|
-
filteredTypes.some((t) => t.id === v.gameVersionTypeID)
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// 获取 CurseForge 游戏版本和版本类型信息
|
|
121
|
+
/**
|
|
122
|
+
* Fetch CurseForge game version and version type information.
|
|
123
|
+
*/
|
|
135
124
|
async function fetchCurseForgeGameVersionInfo(apiToken: string): Promise<{
|
|
136
125
|
versions: CurseForgeGameVersion[];
|
|
137
126
|
types: CurseForgeGameVersionType[];
|
|
@@ -158,7 +147,7 @@ async function fetchCurseForgeGameVersionInfo(apiToken: string): Promise<{
|
|
|
158
147
|
gameVersionTypesRes.data as CurseForgeGameVersionType[];
|
|
159
148
|
|
|
160
149
|
if (!gameVersionTypes.some((x) => x.id === BUKKIT_GAME_VERSION_TYPE.id)) {
|
|
161
|
-
gameVersionTypes.
|
|
150
|
+
gameVersionTypes.push(BUKKIT_GAME_VERSION_TYPE);
|
|
162
151
|
}
|
|
163
152
|
|
|
164
153
|
return {
|
|
@@ -167,33 +156,35 @@ async function fetchCurseForgeGameVersionInfo(apiToken: string): Promise<{
|
|
|
167
156
|
};
|
|
168
157
|
}
|
|
169
158
|
|
|
159
|
+
/**
|
|
160
|
+
* Filter game versions by their type name prefix.
|
|
161
|
+
*/
|
|
162
|
+
function filterGameVersionsByTypeName(
|
|
163
|
+
versions: CurseForgeGameVersion[],
|
|
164
|
+
types: CurseForgeGameVersionType[],
|
|
165
|
+
typeName: string
|
|
166
|
+
): CurseForgeGameVersion[] {
|
|
167
|
+
const filteredTypes = types.filter((x) => x.slug.startsWith(typeName));
|
|
168
|
+
return versions.filter((v) =>
|
|
169
|
+
filteredTypes.some((t) => t.id === v.gameVersionTypeID)
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Find CurseForge game version IDs by their names using a custom comparer.
|
|
175
|
+
*/
|
|
170
176
|
function findCurseForgeGameVersionIdsByNames(
|
|
171
177
|
versions: { id: number; name: string }[],
|
|
172
178
|
names: string[],
|
|
173
179
|
comparer: (a: string, b: string) => boolean = (a, b) =>
|
|
174
|
-
a.toLowerCase() === b.toLowerCase()
|
|
175
|
-
fallbackComparer?: (a: string, b: string) => boolean
|
|
180
|
+
a.toLowerCase() === b.toLowerCase()
|
|
176
181
|
): number[] {
|
|
177
182
|
const result: number[] = [];
|
|
178
183
|
|
|
179
184
|
for (const name of names) {
|
|
180
185
|
let version = versions.find((v) => comparer(v.name, name));
|
|
181
|
-
if (!version && fallbackComparer) {
|
|
182
|
-
version = versions.find((v) => fallbackComparer(v.name, name));
|
|
183
|
-
}
|
|
184
186
|
if (version) result.push(version.id);
|
|
185
187
|
}
|
|
186
188
|
|
|
187
|
-
return
|
|
189
|
+
return result;
|
|
188
190
|
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* 比较器:忽略名称中的 "-Snapshot" 后缀
|
|
192
|
-
*/
|
|
193
|
-
export const CURSEFORGE_GAME_VERSION_SNAPSHOT_NAME_COMPARER = (
|
|
194
|
-
a: string,
|
|
195
|
-
b: string
|
|
196
|
-
): boolean => {
|
|
197
|
-
const normalize = (s: string) => s?.replace(/-snapshot$/i, '') ?? '';
|
|
198
|
-
return normalize(a).toLowerCase() === normalize(b).toLowerCase();
|
|
199
|
-
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { glob } from 'glob';
|
|
2
|
+
import { resolve } from 'path';
|
|
3
|
+
import { PublishContext } from 'semantic-release';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Find files based on provided glob patterns.
|
|
7
|
+
*/
|
|
8
|
+
export async function findFilesByGlob(
|
|
9
|
+
patterns: string[] = [
|
|
10
|
+
'build/libs/!(*-@(dev|sources|javadoc)).jar',
|
|
11
|
+
'build/libs/*-@(dev|sources|javadoc).jar',
|
|
12
|
+
],
|
|
13
|
+
context: PublishContext
|
|
14
|
+
): Promise<string[]> {
|
|
15
|
+
const { logger, cwd } = context;
|
|
16
|
+
|
|
17
|
+
const allFiles: string[] = [];
|
|
18
|
+
|
|
19
|
+
for (const pattern of patterns) {
|
|
20
|
+
logger.log(`Searching for files with pattern: ${pattern}`);
|
|
21
|
+
const files = await glob(pattern, {
|
|
22
|
+
cwd,
|
|
23
|
+
nodir: true,
|
|
24
|
+
});
|
|
25
|
+
allFiles.push(...files);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// 转换为绝对路径
|
|
29
|
+
const files = allFiles.map((file) => resolve(cwd!, file));
|
|
30
|
+
|
|
31
|
+
if (files.length === 0) {
|
|
32
|
+
throw new Error(
|
|
33
|
+
`No files found matching patterns: ${patterns.join(', ')}`
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return files;
|
|
38
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { NextRelease } from 'semantic-release';
|
|
2
|
+
import { PluginConfig } from '../../definitions/plugin-config';
|
|
3
|
+
import { renderTemplates, resolveAndRenderTemplates } from '../template-utils';
|
|
4
|
+
|
|
5
|
+
export function getCurseForgeModLoaders(
|
|
6
|
+
pluginConfig: PluginConfig,
|
|
7
|
+
nextRelease: NextRelease
|
|
8
|
+
): string[] {
|
|
9
|
+
return (
|
|
10
|
+
resolveAndRenderTemplates(
|
|
11
|
+
[pluginConfig.curseforge?.mod_loaders, pluginConfig.mod_loaders],
|
|
12
|
+
{
|
|
13
|
+
nextRelease,
|
|
14
|
+
}
|
|
15
|
+
) || []
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { glob } from 'glob';
|
|
2
|
+
import { resolve } from 'path';
|
|
3
|
+
import { PublishContext } from 'semantic-release';
|
|
4
|
+
import { PluginConfig } from '../../definitions/plugin-config';
|
|
5
|
+
import { findFilesByGlob } from '../glob-utils';
|
|
6
|
+
import { resolveAndRenderTemplates } from '../template-utils';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Find files and primary file for publishing.
|
|
10
|
+
*/
|
|
11
|
+
export async function findFilesAndPrimaryFile(
|
|
12
|
+
pluginConfig: PluginConfig,
|
|
13
|
+
context: PublishContext,
|
|
14
|
+
strategy: Record<string, string>
|
|
15
|
+
): Promise<{ files: string[]; primaryFile: string }> {
|
|
16
|
+
const { nextRelease, logger } = context;
|
|
17
|
+
|
|
18
|
+
const modrinthGlob = resolveAndRenderTemplates(
|
|
19
|
+
[pluginConfig.modrinth?.glob, pluginConfig.glob],
|
|
20
|
+
{
|
|
21
|
+
nextRelease,
|
|
22
|
+
...strategy,
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
const files = await findFilesByGlob(modrinthGlob, context);
|
|
27
|
+
logger.log(
|
|
28
|
+
`Found ${files.length} file(s) for publishing: ${files.join(', ')}`
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
if (files.length === 0) {
|
|
32
|
+
throw new Error('No files found for publishing.');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const primaryPatterns = resolveAndRenderTemplates(
|
|
36
|
+
[
|
|
37
|
+
pluginConfig.modrinth?.primary_file_glob,
|
|
38
|
+
pluginConfig.primary_file_glob,
|
|
39
|
+
],
|
|
40
|
+
{
|
|
41
|
+
nextRelease,
|
|
42
|
+
...strategy,
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
if (primaryPatterns) {
|
|
47
|
+
let primaryCandidates: string[] = [];
|
|
48
|
+
|
|
49
|
+
for (const pattern of primaryPatterns) {
|
|
50
|
+
logger.log(`Searching for primary file with pattern: ${pattern}`);
|
|
51
|
+
const matches = await glob(pattern, {
|
|
52
|
+
cwd: context.cwd,
|
|
53
|
+
nodir: true,
|
|
54
|
+
});
|
|
55
|
+
primaryCandidates.push(
|
|
56
|
+
...matches.map((file) => resolve(context.cwd!, file))
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
primaryCandidates = primaryCandidates.filter((file) =>
|
|
61
|
+
files.includes(file)
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
if (primaryCandidates.length === 1) {
|
|
65
|
+
const primaryFile = primaryCandidates[0];
|
|
66
|
+
logger.log(`Selected primary file: ${primaryFile}`);
|
|
67
|
+
return { files: files, primaryFile };
|
|
68
|
+
} else if (primaryCandidates.length > 1) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`Multiple files matched primary file glob. Please specify a more specific pattern. Found: ${primaryCandidates.join(', ')}`
|
|
71
|
+
);
|
|
72
|
+
} else {
|
|
73
|
+
throw new Error(
|
|
74
|
+
`No files matched primary file glob that were also in the main file list.`
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
} else if (files.length > 1) {
|
|
78
|
+
throw new Error(
|
|
79
|
+
`Multiple files found but no primary file glob specified. Please specify which file should be primary.`
|
|
80
|
+
);
|
|
81
|
+
} else {
|
|
82
|
+
return { files: files, primaryFile: files[0] };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import lodash from 'lodash';
|
|
2
|
+
import { toArray } from './utils';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Renders one or more template strings sequentially using lodash.template.
|
|
6
|
+
*
|
|
7
|
+
* @param templates - A single template string or an array of template strings.
|
|
8
|
+
* @param context - The context object passed to each template during rendering.
|
|
9
|
+
* @returns An array of rendered strings.
|
|
10
|
+
*/
|
|
11
|
+
export function renderTemplates(
|
|
12
|
+
templates: string | string[],
|
|
13
|
+
context: Record<string, any>
|
|
14
|
+
): string[] {
|
|
15
|
+
return toArray(templates).map((tpl) => lodash.template(tpl)(context));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Resolves the first non-empty template from multiple sources and renders it.
|
|
20
|
+
*
|
|
21
|
+
* @param sources - A list of template string sources, ordered by priority (highest first).
|
|
22
|
+
* @param context - The rendering context passed to lodash.template.
|
|
23
|
+
* @returns The rendered string, or undefined if no valid source is found.
|
|
24
|
+
*/
|
|
25
|
+
export function resolveAndRenderTemplate(
|
|
26
|
+
sources: Array<string | undefined | null>,
|
|
27
|
+
context: Record<string, any>
|
|
28
|
+
): string | undefined {
|
|
29
|
+
const source = sources.find(Boolean);
|
|
30
|
+
if (!source) return undefined;
|
|
31
|
+
|
|
32
|
+
return lodash.template(source)(context);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Resolves the first non-empty template (or array of templates) from multiple sources
|
|
37
|
+
* and renders all templates sequentially.
|
|
38
|
+
*
|
|
39
|
+
* @param sources - A list of template sources (string or string array), ordered by priority.
|
|
40
|
+
* @param context - The rendering context passed to lodash.template.
|
|
41
|
+
* @returns An array of rendered strings, or undefined if no valid source is found.
|
|
42
|
+
*/
|
|
43
|
+
export function resolveAndRenderTemplates(
|
|
44
|
+
sources: Array<string | string[] | undefined | null>,
|
|
45
|
+
context: Record<string, any>
|
|
46
|
+
): string[] | undefined {
|
|
47
|
+
const source = sources.find(Boolean);
|
|
48
|
+
if (!source) return undefined;
|
|
49
|
+
|
|
50
|
+
return renderTemplates(
|
|
51
|
+
typeof source === 'string' ? toArray(source) : source,
|
|
52
|
+
context
|
|
53
|
+
);
|
|
54
|
+
}
|
package/src/utils/utils.ts
CHANGED
|
@@ -1,120 +1,10 @@
|
|
|
1
|
-
import { glob } from 'glob';
|
|
2
|
-
import _ from 'lodash';
|
|
3
|
-
import { resolve } from 'path';
|
|
4
|
-
import { NextRelease, PublishContext } from 'semantic-release';
|
|
5
|
-
import { Plugin_config } from '../definitions/plugin_config.js';
|
|
6
|
-
|
|
7
1
|
/**
|
|
8
|
-
*
|
|
9
|
-
*/
|
|
10
|
-
export async function findFiles(
|
|
11
|
-
patterns: string[] = [
|
|
12
|
-
'build/libs/!(*-@(dev|sources|javadoc)).jar',
|
|
13
|
-
'build/libs/*-@(dev|sources|javadoc).jar',
|
|
14
|
-
],
|
|
15
|
-
context: PublishContext
|
|
16
|
-
): Promise<string[]> {
|
|
17
|
-
const { logger, cwd } = context;
|
|
18
|
-
|
|
19
|
-
const allFiles: string[] = [];
|
|
20
|
-
|
|
21
|
-
for (const pattern of patterns) {
|
|
22
|
-
logger.log(`Searching for files with pattern: ${pattern}`);
|
|
23
|
-
const files = await glob(pattern, {
|
|
24
|
-
cwd,
|
|
25
|
-
nodir: true,
|
|
26
|
-
});
|
|
27
|
-
allFiles.push(...files);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// 转换为绝对路径
|
|
31
|
-
const files = allFiles.map((file) => resolve(cwd!, file));
|
|
32
|
-
|
|
33
|
-
if (files.length === 0) {
|
|
34
|
-
throw new Error(
|
|
35
|
-
`No files found matching patterns: ${patterns.join(', ')}`
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return files;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* 依次使用 lodash.template 渲染字符串数组。
|
|
44
|
-
* @param templates 字符串模板数组
|
|
45
|
-
* @param context 模板变量上下文对象
|
|
46
|
-
* @returns 渲染后的字符串数组
|
|
47
|
-
*/
|
|
48
|
-
export function renderTemplates(
|
|
49
|
-
templates: string[],
|
|
50
|
-
context: Record<string, any>
|
|
51
|
-
): string[] {
|
|
52
|
-
return templates.map((tpl) => _.template(tpl)(context));
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* 从多个来源中按优先级选择第一个非空模板并渲染。
|
|
57
|
-
* @param sources 模板字符串来源(优先级从高到低)
|
|
58
|
-
* @param context 模板渲染上下文(传给 lodash.template)
|
|
59
|
-
* @returns 渲染后的字符串或 undefined
|
|
60
|
-
*/
|
|
61
|
-
export function resolveTemplate(
|
|
62
|
-
sources: Array<string | undefined | null>,
|
|
63
|
-
context: Record<string, any>
|
|
64
|
-
): string | undefined {
|
|
65
|
-
const source = sources.find(Boolean);
|
|
66
|
-
if (!source) return undefined;
|
|
67
|
-
|
|
68
|
-
return _.template(source)(context);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export function resolveMultipleTemplate(
|
|
72
|
-
sources: Array<string | string[] | undefined | null>,
|
|
73
|
-
context: Record<string, any>
|
|
74
|
-
): string[] | undefined {
|
|
75
|
-
const source = sources.find(Boolean);
|
|
76
|
-
if (!source) return undefined;
|
|
77
|
-
|
|
78
|
-
return renderTemplates(
|
|
79
|
-
typeof source === 'string' ? toArray(source) : source,
|
|
80
|
-
context
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* 确保给定的值总是以数组形式返回。
|
|
2
|
+
* Ensures that the given value is always returned as an array.
|
|
86
3
|
*
|
|
87
|
-
* @param value -
|
|
88
|
-
* @returns
|
|
4
|
+
* @param value - A single item, an array of items, or null/undefined.
|
|
5
|
+
* @returns An array. If the input is not an array, it will be wrapped into one.
|
|
89
6
|
*/
|
|
90
|
-
export function toArray<T>(value: T | T[]): T[] {
|
|
7
|
+
export function toArray<T>(value: T | T[] | undefined | null): T[] {
|
|
8
|
+
if (value == null) return [];
|
|
91
9
|
return Array.isArray(value) ? value : [value];
|
|
92
10
|
}
|
|
93
|
-
|
|
94
|
-
export function getCurseForgeModLoaders(
|
|
95
|
-
pluginConfig: Plugin_config,
|
|
96
|
-
env: Record<string, string>,
|
|
97
|
-
nextRelease: NextRelease
|
|
98
|
-
): string[] {
|
|
99
|
-
const curseforge = pluginConfig.curseforge;
|
|
100
|
-
|
|
101
|
-
let modLoaders: string[] | undefined;
|
|
102
|
-
if (curseforge?.mod_loaders && curseforge.mod_loaders.length > 0) {
|
|
103
|
-
modLoaders = renderTemplates(toArray(curseforge.mod_loaders), {
|
|
104
|
-
nextRelease,
|
|
105
|
-
});
|
|
106
|
-
} else if (
|
|
107
|
-
pluginConfig.mod_loaders &&
|
|
108
|
-
pluginConfig.mod_loaders.length > 0
|
|
109
|
-
) {
|
|
110
|
-
modLoaders = renderTemplates(toArray(pluginConfig.mod_loaders), {
|
|
111
|
-
nextRelease,
|
|
112
|
-
}) as string[];
|
|
113
|
-
} else if (env.CURSEFORGE_MOD_LOADERS) {
|
|
114
|
-
modLoaders = env.CURSEFORGE_MOD_LOADERS.split(',').map((s) => s.trim());
|
|
115
|
-
} else if (env.MOD_LOADERS) {
|
|
116
|
-
modLoaders = env.MOD_LOADERS.split(',').map((s) => s.trim());
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return modLoaders || [];
|
|
120
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"plugin_config.d.ts","sourceRoot":"","sources":["../../src/definitions/plugin_config.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG;IAExB,YAAY,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IAC5C,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAGzB,UAAU,CAAC,EAAE;QACT,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAClC,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAClC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QACjC,yBAAyB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAC9C,uBAAuB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAC5C,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QAChC,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;QAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,4BAA4B,CAAC,EAAE,OAAO,CAAC;QACvC,SAAS,CAAC,EAAE;YACR,QAAQ,CAAC,EAAE,KAAK,CAAC;gBACb,IAAI,EAAE,MAAM,CAAC;gBACb,UAAU,CAAC,EAAE,MAAM,CAAC;gBACpB,IAAI,EACE,kBAAkB,GAClB,cAAc,GACd,qBAAqB,GACrB,qBAAqB,GACrB,MAAM,CAAC;aAChB,CAAC,CAAC;SACN,CAAC;QACF,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;KAC5B,CAAC;IACF,QAAQ,CAAC,EAAE;QACP,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QACvB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,YAAY,CAAC,EAAE,KAAK,CAAC;YACjB,UAAU,CAAC,EAAE,MAAM,CAAC;YACpB,UAAU,CAAC,EAAE,MAAM,CAAC;YACpB,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,eAAe,EACT,UAAU,GACV,UAAU,GACV,cAAc,GACd,UAAU,CAAC;SACpB,CAAC,CAAC;QACH,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,MAAM,CAAC,EACD,QAAQ,GACR,UAAU,GACV,OAAO,GACP,UAAU,GACV,WAAW,GACX,SAAS,CAAC;QAChB,gBAAgB,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;QAChE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QACzB,iBAAiB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;KACzC,CAAC;CACL,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"plugin_config.js","sourceRoot":"","sources":["../../src/definitions/plugin_config.ts"],"names":[],"mappings":""}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
export type Plugin_config = {
|
|
2
|
-
// 全局发布相关配置
|
|
3
|
-
release_type?: 'alpha' | 'beta' | 'release'; // 全局发布类型
|
|
4
|
-
game_versions?: string | string[]; // 全局游戏版本列表
|
|
5
|
-
mod_loaders?: string | string[]; // 全局模组加载器列表
|
|
6
|
-
display_name?: string;
|
|
7
|
-
|
|
8
|
-
// 全局文件查找相关配置(如果平台没有指定自己的 glob,则使用此配置)
|
|
9
|
-
glob?: string | string[]; // glob 模式,用于查找要发布的文件
|
|
10
|
-
|
|
11
|
-
// Minecraft 发布相关配置
|
|
12
|
-
curseforge?: {
|
|
13
|
-
project_id: string;
|
|
14
|
-
game_versions?: string | string[]; // CurseForge 专用的游戏版本列表
|
|
15
|
-
java_versions?: string | string[];
|
|
16
|
-
environments?: string | string[];
|
|
17
|
-
game_versions_for_plugins?: string | string[];
|
|
18
|
-
game_versions_for_addon?: string | string[];
|
|
19
|
-
mod_loaders?: string | string[]; // CurseForge 专用的模组加载器列表
|
|
20
|
-
changelog?: string;
|
|
21
|
-
changelog_type?: 'text' | 'html' | 'markdown';
|
|
22
|
-
display_name?: string; // 可选:网站上显示的友好名称
|
|
23
|
-
parent_file_id?: number; // 可选:此文件的父文件 ID
|
|
24
|
-
is_marked_for_manual_release?: boolean; // 可选:如果为 true,文件获批后不会立即发布
|
|
25
|
-
relations?: {
|
|
26
|
-
projects?: Array<{
|
|
27
|
-
slug: string; // 相关插件的 slug
|
|
28
|
-
project_id?: string; // 可选:用于精确匹配项目
|
|
29
|
-
type:
|
|
30
|
-
| 'embedded_library'
|
|
31
|
-
| 'incompatible'
|
|
32
|
-
| 'optional_dependency'
|
|
33
|
-
| 'required_dependency'
|
|
34
|
-
| 'tool';
|
|
35
|
-
}>;
|
|
36
|
-
};
|
|
37
|
-
glob?: string | string[]; // CurseForge 专用的 glob 模式,用于查找要发布的 JAR 文件
|
|
38
|
-
};
|
|
39
|
-
modrinth?: {
|
|
40
|
-
project_id: string;
|
|
41
|
-
version_number?: string;
|
|
42
|
-
display_name?: string;
|
|
43
|
-
game_versions?: string[]; // Modrinth 专用的游戏版本列表
|
|
44
|
-
mod_loaders?: string[]; // Modrinth 专用的模组加载器列表
|
|
45
|
-
changelog?: string;
|
|
46
|
-
dependencies?: Array<{
|
|
47
|
-
version_id?: string; // 可选:依赖版本的 ID
|
|
48
|
-
project_id?: string; // 可选:依赖项目的 ID
|
|
49
|
-
file_name?: string; // 可选:依赖的文件名
|
|
50
|
-
dependency_type:
|
|
51
|
-
| 'required'
|
|
52
|
-
| 'optional'
|
|
53
|
-
| 'incompatible'
|
|
54
|
-
| 'embedded'; // 依赖类型
|
|
55
|
-
}>;
|
|
56
|
-
featured?: boolean; // 是否标记为特色版本
|
|
57
|
-
status?:
|
|
58
|
-
| 'listed'
|
|
59
|
-
| 'archived'
|
|
60
|
-
| 'draft'
|
|
61
|
-
| 'unlisted'
|
|
62
|
-
| 'scheduled'
|
|
63
|
-
| 'unknown'; // 版本状态
|
|
64
|
-
requested_status?: 'listed' | 'archived' | 'draft' | 'unlisted'; // 请求的状态
|
|
65
|
-
glob?: string | string[]; // Modrinth 专用的 glob 模式
|
|
66
|
-
primary_file_glob?: string | string[]; // 用于匹配主要文件的 glob 模式
|
|
67
|
-
};
|
|
68
|
-
};
|