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
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { glob } from 'glob';
|
|
2
|
+
import { resolve } from 'path';
|
|
3
|
+
import { findFilesByGlob } from '../glob-utils';
|
|
4
|
+
import { resolveAndRenderTemplates } from '../template-utils';
|
|
5
|
+
/**
|
|
6
|
+
* Find files and primary file for publishing.
|
|
7
|
+
*/
|
|
8
|
+
export async function findFilesAndPrimaryFile(pluginConfig, context, strategy) {
|
|
9
|
+
const { nextRelease, logger } = context;
|
|
10
|
+
const modrinthGlob = resolveAndRenderTemplates([pluginConfig.modrinth?.glob, pluginConfig.glob], {
|
|
11
|
+
nextRelease,
|
|
12
|
+
...strategy,
|
|
13
|
+
});
|
|
14
|
+
const files = await findFilesByGlob(modrinthGlob, context);
|
|
15
|
+
logger.log(`Found ${files.length} file(s) for publishing: ${files.join(', ')}`);
|
|
16
|
+
if (files.length === 0) {
|
|
17
|
+
throw new Error('No files found for publishing.');
|
|
18
|
+
}
|
|
19
|
+
const primaryPatterns = resolveAndRenderTemplates([
|
|
20
|
+
pluginConfig.modrinth?.primary_file_glob,
|
|
21
|
+
pluginConfig.primary_file_glob,
|
|
22
|
+
], {
|
|
23
|
+
nextRelease,
|
|
24
|
+
...strategy,
|
|
25
|
+
});
|
|
26
|
+
if (primaryPatterns) {
|
|
27
|
+
let primaryCandidates = [];
|
|
28
|
+
for (const pattern of primaryPatterns) {
|
|
29
|
+
logger.log(`Searching for primary file with pattern: ${pattern}`);
|
|
30
|
+
const matches = await glob(pattern, {
|
|
31
|
+
cwd: context.cwd,
|
|
32
|
+
nodir: true,
|
|
33
|
+
});
|
|
34
|
+
primaryCandidates.push(...matches.map((file) => resolve(context.cwd, file)));
|
|
35
|
+
}
|
|
36
|
+
primaryCandidates = primaryCandidates.filter((file) => files.includes(file));
|
|
37
|
+
if (primaryCandidates.length === 1) {
|
|
38
|
+
const primaryFile = primaryCandidates[0];
|
|
39
|
+
logger.log(`Selected primary file: ${primaryFile}`);
|
|
40
|
+
return { files: files, primaryFile };
|
|
41
|
+
}
|
|
42
|
+
else if (primaryCandidates.length > 1) {
|
|
43
|
+
throw new Error(`Multiple files matched primary file glob. Please specify a more specific pattern. Found: ${primaryCandidates.join(', ')}`);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
throw new Error(`No files matched primary file glob that were also in the main file list.`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else if (files.length > 1) {
|
|
50
|
+
throw new Error(`Multiple files found but no primary file glob specified. Please specify which file should be primary.`);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
return { files: files, primaryFile: files[0] };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/utils/platform/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAG/B,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAE9D;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CACzC,YAA0B,EAC1B,OAAuB,EACvB,QAAgC;IAEhC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAExC,MAAM,YAAY,GAAG,yBAAyB,CAC1C,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,EAChD;QACI,WAAW;QACX,GAAG,QAAQ;KACd,CACJ,CAAC;IAEF,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAC3D,MAAM,CAAC,GAAG,CACN,SAAS,KAAK,CAAC,MAAM,4BAA4B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACtE,CAAC;IAEF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,eAAe,GAAG,yBAAyB,CAC7C;QACI,YAAY,CAAC,QAAQ,EAAE,iBAAiB;QACxC,YAAY,CAAC,iBAAiB;KACjC,EACD;QACI,WAAW;QACX,GAAG,QAAQ;KACd,CACJ,CAAC;IAEF,IAAI,eAAe,EAAE,CAAC;QAClB,IAAI,iBAAiB,GAAa,EAAE,CAAC;QAErC,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;YACpC,MAAM,CAAC,GAAG,CAAC,4CAA4C,OAAO,EAAE,CAAC,CAAC;YAClE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE;gBAChC,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,KAAK,EAAE,IAAI;aACd,CAAC,CAAC;YACH,iBAAiB,CAAC,IAAI,CAClB,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,GAAI,EAAE,IAAI,CAAC,CAAC,CACxD,CAAC;QACN,CAAC;QAED,iBAAiB,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAClD,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CACvB,CAAC;QAEF,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,MAAM,WAAW,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;YACzC,MAAM,CAAC,GAAG,CAAC,0BAA0B,WAAW,EAAE,CAAC,CAAC;YACpD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;QACzC,CAAC;aAAM,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CACX,4FAA4F,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC7H,CAAC;QACN,CAAC;aAAM,CAAC;YACJ,MAAM,IAAI,KAAK,CACX,0EAA0E,CAC7E,CAAC;QACN,CAAC;IACL,CAAC;SAAM,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACX,uGAAuG,CAC1G,CAAC;IACN,CAAC;SAAM,CAAC;QACJ,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACnD,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders one or more template strings sequentially using lodash.template.
|
|
3
|
+
*
|
|
4
|
+
* @param templates - A single template string or an array of template strings.
|
|
5
|
+
* @param context - The context object passed to each template during rendering.
|
|
6
|
+
* @returns An array of rendered strings.
|
|
7
|
+
*/
|
|
8
|
+
export declare function renderTemplates(templates: string | string[], context: Record<string, any>): string[];
|
|
9
|
+
/**
|
|
10
|
+
* Resolves the first non-empty template from multiple sources and renders it.
|
|
11
|
+
*
|
|
12
|
+
* @param sources - A list of template string sources, ordered by priority (highest first).
|
|
13
|
+
* @param context - The rendering context passed to lodash.template.
|
|
14
|
+
* @returns The rendered string, or undefined if no valid source is found.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveAndRenderTemplate(sources: Array<string | undefined | null>, context: Record<string, any>): string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Resolves the first non-empty template (or array of templates) from multiple sources
|
|
19
|
+
* and renders all templates sequentially.
|
|
20
|
+
*
|
|
21
|
+
* @param sources - A list of template sources (string or string array), ordered by priority.
|
|
22
|
+
* @param context - The rendering context passed to lodash.template.
|
|
23
|
+
* @returns An array of rendered strings, or undefined if no valid source is found.
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveAndRenderTemplates(sources: Array<string | string[] | undefined | null>, context: Record<string, any>): string[] | undefined;
|
|
26
|
+
//# sourceMappingURL=template-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-utils.d.ts","sourceRoot":"","sources":["../../src/utils/template-utils.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC3B,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC7B,MAAM,EAAE,CAEV;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACpC,OAAO,EAAE,KAAK,CAAC,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC,EACzC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC7B,MAAM,GAAG,SAAS,CAKpB;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACrC,OAAO,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,GAAG,IAAI,CAAC,EACpD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC7B,MAAM,EAAE,GAAG,SAAS,CAQtB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import lodash from 'lodash';
|
|
2
|
+
import { toArray } from './utils';
|
|
3
|
+
/**
|
|
4
|
+
* Renders one or more template strings sequentially using lodash.template.
|
|
5
|
+
*
|
|
6
|
+
* @param templates - A single template string or an array of template strings.
|
|
7
|
+
* @param context - The context object passed to each template during rendering.
|
|
8
|
+
* @returns An array of rendered strings.
|
|
9
|
+
*/
|
|
10
|
+
export function renderTemplates(templates, context) {
|
|
11
|
+
return toArray(templates).map((tpl) => lodash.template(tpl)(context));
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Resolves the first non-empty template from multiple sources and renders it.
|
|
15
|
+
*
|
|
16
|
+
* @param sources - A list of template string sources, ordered by priority (highest first).
|
|
17
|
+
* @param context - The rendering context passed to lodash.template.
|
|
18
|
+
* @returns The rendered string, or undefined if no valid source is found.
|
|
19
|
+
*/
|
|
20
|
+
export function resolveAndRenderTemplate(sources, context) {
|
|
21
|
+
const source = sources.find(Boolean);
|
|
22
|
+
if (!source)
|
|
23
|
+
return undefined;
|
|
24
|
+
return lodash.template(source)(context);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Resolves the first non-empty template (or array of templates) from multiple sources
|
|
28
|
+
* and renders all templates sequentially.
|
|
29
|
+
*
|
|
30
|
+
* @param sources - A list of template sources (string or string array), ordered by priority.
|
|
31
|
+
* @param context - The rendering context passed to lodash.template.
|
|
32
|
+
* @returns An array of rendered strings, or undefined if no valid source is found.
|
|
33
|
+
*/
|
|
34
|
+
export function resolveAndRenderTemplates(sources, context) {
|
|
35
|
+
const source = sources.find(Boolean);
|
|
36
|
+
if (!source)
|
|
37
|
+
return undefined;
|
|
38
|
+
return renderTemplates(typeof source === 'string' ? toArray(source) : source, context);
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=template-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-utils.js","sourceRoot":"","sources":["../../src/utils/template-utils.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC3B,SAA4B,EAC5B,OAA4B;IAE5B,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CACpC,OAAyC,EACzC,OAA4B;IAE5B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAE9B,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,yBAAyB,CACrC,OAAoD,EACpD,OAA4B;IAE5B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAE9B,OAAO,eAAe,CAClB,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,EACrD,OAAO,CACV,CAAC;AACN,CAAC"}
|
package/dist/utils/utils.d.ts
CHANGED
|
@@ -1,30 +1,8 @@
|
|
|
1
|
-
import { NextRelease, PublishContext } from 'semantic-release';
|
|
2
|
-
import { Plugin_config } from '../definitions/plugin_config.js';
|
|
3
1
|
/**
|
|
4
|
-
*
|
|
5
|
-
*/
|
|
6
|
-
export declare function findFiles(patterns: string[] | undefined, context: PublishContext): Promise<string[]>;
|
|
7
|
-
/**
|
|
8
|
-
* 依次使用 lodash.template 渲染字符串数组。
|
|
9
|
-
* @param templates 字符串模板数组
|
|
10
|
-
* @param context 模板变量上下文对象
|
|
11
|
-
* @returns 渲染后的字符串数组
|
|
12
|
-
*/
|
|
13
|
-
export declare function renderTemplates(templates: string[], context: Record<string, any>): string[];
|
|
14
|
-
/**
|
|
15
|
-
* 从多个来源中按优先级选择第一个非空模板并渲染。
|
|
16
|
-
* @param sources 模板字符串来源(优先级从高到低)
|
|
17
|
-
* @param context 模板渲染上下文(传给 lodash.template)
|
|
18
|
-
* @returns 渲染后的字符串或 undefined
|
|
19
|
-
*/
|
|
20
|
-
export declare function resolveTemplate(sources: Array<string | undefined | null>, context: Record<string, any>): string | undefined;
|
|
21
|
-
export declare function resolveMultipleTemplate(sources: Array<string | string[] | undefined | null>, context: Record<string, any>): string[] | undefined;
|
|
22
|
-
/**
|
|
23
|
-
* 确保给定的值总是以数组形式返回。
|
|
2
|
+
* Ensures that the given value is always returned as an array.
|
|
24
3
|
*
|
|
25
|
-
* @param value -
|
|
26
|
-
* @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.
|
|
27
6
|
*/
|
|
28
|
-
export declare function toArray<T>(value: T | T[]): T[];
|
|
29
|
-
export declare function getCurseForgeModLoaders(pluginConfig: Plugin_config, env: Record<string, string>, nextRelease: NextRelease): string[];
|
|
7
|
+
export declare function toArray<T>(value: T | T[] | undefined | null): T[];
|
|
30
8
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,SAAS,GAAG,IAAI,GAAG,CAAC,EAAE,CAGjE"}
|
package/dist/utils/utils.js
CHANGED
|
@@ -1,86 +1,12 @@
|
|
|
1
|
-
import { glob } from 'glob';
|
|
2
|
-
import _ from 'lodash';
|
|
3
|
-
import { resolve } from 'path';
|
|
4
1
|
/**
|
|
5
|
-
*
|
|
6
|
-
*/
|
|
7
|
-
export async function findFiles(patterns = [
|
|
8
|
-
'build/libs/!(*-@(dev|sources|javadoc)).jar',
|
|
9
|
-
'build/libs/*-@(dev|sources|javadoc).jar',
|
|
10
|
-
], context) {
|
|
11
|
-
const { logger, cwd } = context;
|
|
12
|
-
const allFiles = [];
|
|
13
|
-
for (const pattern of patterns) {
|
|
14
|
-
logger.log(`Searching for files with pattern: ${pattern}`);
|
|
15
|
-
const files = await glob(pattern, {
|
|
16
|
-
cwd,
|
|
17
|
-
nodir: true,
|
|
18
|
-
});
|
|
19
|
-
allFiles.push(...files);
|
|
20
|
-
}
|
|
21
|
-
// 转换为绝对路径
|
|
22
|
-
const files = allFiles.map((file) => resolve(cwd, file));
|
|
23
|
-
if (files.length === 0) {
|
|
24
|
-
throw new Error(`No files found matching patterns: ${patterns.join(', ')}`);
|
|
25
|
-
}
|
|
26
|
-
return files;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* 依次使用 lodash.template 渲染字符串数组。
|
|
30
|
-
* @param templates 字符串模板数组
|
|
31
|
-
* @param context 模板变量上下文对象
|
|
32
|
-
* @returns 渲染后的字符串数组
|
|
33
|
-
*/
|
|
34
|
-
export function renderTemplates(templates, context) {
|
|
35
|
-
return templates.map((tpl) => _.template(tpl)(context));
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* 从多个来源中按优先级选择第一个非空模板并渲染。
|
|
39
|
-
* @param sources 模板字符串来源(优先级从高到低)
|
|
40
|
-
* @param context 模板渲染上下文(传给 lodash.template)
|
|
41
|
-
* @returns 渲染后的字符串或 undefined
|
|
42
|
-
*/
|
|
43
|
-
export function resolveTemplate(sources, context) {
|
|
44
|
-
const source = sources.find(Boolean);
|
|
45
|
-
if (!source)
|
|
46
|
-
return undefined;
|
|
47
|
-
return _.template(source)(context);
|
|
48
|
-
}
|
|
49
|
-
export function resolveMultipleTemplate(sources, context) {
|
|
50
|
-
const source = sources.find(Boolean);
|
|
51
|
-
if (!source)
|
|
52
|
-
return undefined;
|
|
53
|
-
return renderTemplates(typeof source === 'string' ? toArray(source) : source, context);
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* 确保给定的值总是以数组形式返回。
|
|
2
|
+
* Ensures that the given value is always returned as an array.
|
|
57
3
|
*
|
|
58
|
-
* @param value -
|
|
59
|
-
* @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.
|
|
60
6
|
*/
|
|
61
7
|
export function toArray(value) {
|
|
8
|
+
if (value == null)
|
|
9
|
+
return [];
|
|
62
10
|
return Array.isArray(value) ? value : [value];
|
|
63
11
|
}
|
|
64
|
-
export function getCurseForgeModLoaders(pluginConfig, env, nextRelease) {
|
|
65
|
-
const curseforge = pluginConfig.curseforge;
|
|
66
|
-
let modLoaders;
|
|
67
|
-
if (curseforge?.mod_loaders && curseforge.mod_loaders.length > 0) {
|
|
68
|
-
modLoaders = renderTemplates(toArray(curseforge.mod_loaders), {
|
|
69
|
-
nextRelease,
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
else if (pluginConfig.mod_loaders &&
|
|
73
|
-
pluginConfig.mod_loaders.length > 0) {
|
|
74
|
-
modLoaders = renderTemplates(toArray(pluginConfig.mod_loaders), {
|
|
75
|
-
nextRelease,
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
else if (env.CURSEFORGE_MOD_LOADERS) {
|
|
79
|
-
modLoaders = env.CURSEFORGE_MOD_LOADERS.split(',').map((s) => s.trim());
|
|
80
|
-
}
|
|
81
|
-
else if (env.MOD_LOADERS) {
|
|
82
|
-
modLoaders = env.MOD_LOADERS.split(',').map((s) => s.trim());
|
|
83
|
-
}
|
|
84
|
-
return modLoaders || [];
|
|
85
|
-
}
|
|
86
12
|
//# sourceMappingURL=utils.js.map
|
package/dist/utils/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAI,KAAiC;IACxD,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAC7B,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAClD,CAAC"}
|
package/package.json
CHANGED
package/src/curseforge.ts
CHANGED
|
@@ -1,200 +1,138 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
2
|
import FormData from 'form-data';
|
|
3
3
|
import { readFile } from 'fs/promises';
|
|
4
|
+
import { basename } from 'path';
|
|
4
5
|
import { PublishContext } from 'semantic-release';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
resolveMultipleTemplate,
|
|
10
|
-
resolveTemplate,
|
|
11
|
-
} from './utils/utils.js';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* 为 CurseForge 查找单个文件
|
|
15
|
-
*/
|
|
16
|
-
async function findFileCurseforge(
|
|
17
|
-
pluginConfig: Plugin_config,
|
|
18
|
-
context: PublishContext
|
|
19
|
-
): Promise<string> {
|
|
20
|
-
const { env, logger } = context;
|
|
21
|
-
const version = context.nextRelease.version;
|
|
22
|
-
|
|
23
|
-
const curseforgeGlob = resolveMultipleTemplate(
|
|
24
|
-
[
|
|
25
|
-
pluginConfig.curseforge?.glob,
|
|
26
|
-
pluginConfig.glob,
|
|
27
|
-
env.CURSEFORGE_GLOB,
|
|
28
|
-
env.GLOB,
|
|
29
|
-
],
|
|
30
|
-
{
|
|
31
|
-
nextRelease: context.nextRelease,
|
|
32
|
-
}
|
|
33
|
-
);
|
|
6
|
+
import { PluginConfig } from './definitions/plugin-config.js';
|
|
7
|
+
import { getCurseForgeModLoaders } from './utils/platform/curseforge-utils';
|
|
8
|
+
import { findFilesAndPrimaryFile } from './utils/platform/utils';
|
|
9
|
+
import { resolveAndRenderTemplate } from './utils/template-utils';
|
|
34
10
|
|
|
35
|
-
|
|
36
|
-
|
|
11
|
+
export async function publishToCurseforge(
|
|
12
|
+
pluginConfig: PluginConfig,
|
|
13
|
+
context: PublishContext,
|
|
14
|
+
strategy: Record<string, string>,
|
|
15
|
+
curseforgeGameVersionIds?: number[]
|
|
16
|
+
): Promise<number> {
|
|
17
|
+
const { logger } = context;
|
|
18
|
+
const { curseforge } = pluginConfig;
|
|
37
19
|
|
|
38
|
-
|
|
39
|
-
if (files.length === 1) {
|
|
40
|
-
logger.log(`Using the only found file for CurseForge: ${files[0]}`);
|
|
41
|
-
return files[0];
|
|
42
|
-
}
|
|
20
|
+
const projectId = curseforge!.project_id!;
|
|
43
21
|
|
|
22
|
+
const { files, primaryFile } = await findFilesAndPrimaryFile(
|
|
23
|
+
pluginConfig,
|
|
24
|
+
context,
|
|
25
|
+
strategy
|
|
26
|
+
);
|
|
44
27
|
logger.log(
|
|
45
|
-
`
|
|
28
|
+
`Publishing ${files.length} file(s) to CurseForge project ${projectId}...`
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
let primaryFileId = await uploadCurseForgeFile(
|
|
32
|
+
pluginConfig,
|
|
33
|
+
context,
|
|
34
|
+
curseforgeGameVersionIds,
|
|
35
|
+
primaryFile
|
|
46
36
|
);
|
|
47
37
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (versionedFiles.length === 1) {
|
|
52
|
-
logger.log(
|
|
53
|
-
`Using versioned file for CurseForge: ${versionedFiles[0]}`
|
|
54
|
-
);
|
|
55
|
-
return versionedFiles[0];
|
|
56
|
-
} else if (versionedFiles.length > 1) {
|
|
57
|
-
throw new Error(
|
|
58
|
-
`Multiple files found containing version ${version} for CurseForge. Please specify a more specific glob pattern. Found: ${versionedFiles.join(', ')}`
|
|
59
|
-
);
|
|
38
|
+
for (const filePath of files) {
|
|
39
|
+
if (filePath === primaryFile) {
|
|
40
|
+
continue;
|
|
60
41
|
}
|
|
42
|
+
|
|
43
|
+
await uploadCurseForgeFile(
|
|
44
|
+
pluginConfig,
|
|
45
|
+
context,
|
|
46
|
+
curseforgeGameVersionIds,
|
|
47
|
+
filePath,
|
|
48
|
+
primaryFileId
|
|
49
|
+
);
|
|
61
50
|
}
|
|
62
51
|
|
|
63
|
-
|
|
64
|
-
throw new Error(
|
|
65
|
-
`Multiple files found for CurseForge but could not determine which to use. Found: ${files.join(', ')}`
|
|
66
|
-
);
|
|
52
|
+
return primaryFileId;
|
|
67
53
|
}
|
|
68
54
|
|
|
69
|
-
|
|
70
|
-
pluginConfig:
|
|
55
|
+
async function uploadCurseForgeFile(
|
|
56
|
+
pluginConfig: PluginConfig,
|
|
71
57
|
context: PublishContext,
|
|
72
|
-
curseforgeGameVersionIds
|
|
73
|
-
|
|
58
|
+
curseforgeGameVersionIds: number[] | undefined,
|
|
59
|
+
filePath: string,
|
|
60
|
+
primaryFileId?: number
|
|
61
|
+
): Promise<number> {
|
|
74
62
|
const { env, logger } = context;
|
|
75
63
|
const { curseforge } = pluginConfig;
|
|
64
|
+
|
|
76
65
|
const apiKey = env.CURSEFORGE_TOKEN!;
|
|
77
66
|
const projectId = curseforge!.project_id!;
|
|
78
|
-
const nextRelease = context.nextRelease;
|
|
79
|
-
|
|
80
|
-
// 查找单个文件
|
|
81
|
-
const filePath = await findFileCurseforge(pluginConfig, context);
|
|
82
|
-
logger.log(
|
|
83
|
-
`Publishing file ${filePath} to CurseForge project ${projectId}...`
|
|
84
|
-
);
|
|
85
67
|
|
|
86
68
|
const form = new FormData();
|
|
87
69
|
const file = await readFile(filePath);
|
|
88
70
|
form.append('file', file, {
|
|
89
|
-
filename: filePath
|
|
71
|
+
filename: basename(filePath),
|
|
90
72
|
});
|
|
91
73
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
curseforge?.display_name,
|
|
97
|
-
pluginConfig.display_name,
|
|
98
|
-
env.CURSEFORGE_DISPLAY_NAME,
|
|
99
|
-
env.DISPLAY_NAME,
|
|
100
|
-
],
|
|
101
|
-
{ nextRelease }
|
|
74
|
+
const metadata = prepareMetadata(
|
|
75
|
+
pluginConfig,
|
|
76
|
+
context,
|
|
77
|
+
curseforgeGameVersionIds
|
|
102
78
|
);
|
|
103
79
|
|
|
104
|
-
|
|
80
|
+
if (primaryFileId) {
|
|
81
|
+
metadata.parentFileID = primaryFileId;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
form.append('metadata', metadata);
|
|
85
|
+
|
|
86
|
+
const response = await axios.post(
|
|
87
|
+
`https://upload.curseforge.com/api/projects/${projectId}/upload-file`,
|
|
88
|
+
form,
|
|
89
|
+
{
|
|
90
|
+
headers: {
|
|
91
|
+
...form.getHeaders(),
|
|
92
|
+
'X-API-TOKEN': apiKey,
|
|
93
|
+
},
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const resData = response.data;
|
|
98
|
+
|
|
99
|
+
if (resData && typeof resData.id === 'number') {
|
|
100
|
+
logger.log(
|
|
101
|
+
`Successfully published to CurseForge, File ID: ${resData.id}`
|
|
102
|
+
);
|
|
103
|
+
return resData.id;
|
|
104
|
+
} else {
|
|
105
|
+
throw new Error(
|
|
106
|
+
`CurseForge API returned unexpected response: ${resData}`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function prepareMetadata(
|
|
112
|
+
pluginConfig: PluginConfig,
|
|
113
|
+
context: PublishContext,
|
|
114
|
+
curseforgeGameVersionIds: number[] | undefined
|
|
115
|
+
) {
|
|
116
|
+
const { nextRelease } = context;
|
|
117
|
+
const { curseforge } = pluginConfig;
|
|
105
118
|
const metadata: any = {
|
|
106
119
|
gameVersions: curseforgeGameVersionIds,
|
|
107
120
|
releaseType: pluginConfig.release_type || 'release',
|
|
108
121
|
changelog: curseforge?.changelog || context.nextRelease.notes,
|
|
109
122
|
changelogType: curseforge?.changelog_type || 'markdown',
|
|
123
|
+
isMarkedForManualRelease:
|
|
124
|
+
curseforge?.is_marked_for_manual_release || false,
|
|
125
|
+
relations: curseforge?.relations || [],
|
|
110
126
|
};
|
|
111
127
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
} else {
|
|
116
|
-
// 如果没有找到任何配置,使用默认值
|
|
117
|
-
metadata.displayName = context.nextRelease.name;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// 添加 metadataModLoaders(如果有值)
|
|
121
|
-
const metadataModLoaders = getCurseForgeModLoaders(
|
|
122
|
-
pluginConfig,
|
|
123
|
-
env,
|
|
124
|
-
nextRelease
|
|
128
|
+
const displayName = resolveAndRenderTemplate(
|
|
129
|
+
[curseforge?.display_name, pluginConfig.display_name],
|
|
130
|
+
{ nextRelease }
|
|
125
131
|
);
|
|
126
|
-
if (metadataModLoaders) {
|
|
127
|
-
metadata.modLoaders = metadataModLoaders;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// 只有当提供值时才添加这三个特定字段
|
|
131
|
-
if (curseforge?.parent_file_id !== undefined) {
|
|
132
|
-
metadata.parentFileID = curseforge.parent_file_id;
|
|
133
|
-
}
|
|
134
132
|
|
|
135
|
-
|
|
136
|
-
metadata.isMarkedForManualRelease =
|
|
137
|
-
curseforge.is_marked_for_manual_release;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (curseforge?.relations && Object.keys(curseforge.relations).length > 0) {
|
|
141
|
-
metadata.relations = curseforge.relations;
|
|
142
|
-
}
|
|
133
|
+
metadata.display_name = displayName || context.nextRelease.name;
|
|
143
134
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
try {
|
|
147
|
-
const response = await axios.post(
|
|
148
|
-
`https://upload.curseforge.com/api/projects/${projectId}/upload-file`,
|
|
149
|
-
form,
|
|
150
|
-
{
|
|
151
|
-
headers: {
|
|
152
|
-
...form.getHeaders(),
|
|
153
|
-
'X-API-TOKEN': apiKey,
|
|
154
|
-
},
|
|
155
|
-
}
|
|
156
|
-
);
|
|
135
|
+
metadata.modLoaders = getCurseForgeModLoaders(pluginConfig, nextRelease);
|
|
157
136
|
|
|
158
|
-
|
|
159
|
-
if (response.data && typeof response.data.id === 'number') {
|
|
160
|
-
logger.log(
|
|
161
|
-
`Successfully published to CurseForge: ${response.data.displayName || `File ID: ${response.data.id}`}`
|
|
162
|
-
);
|
|
163
|
-
return response.data.id.toString();
|
|
164
|
-
} else {
|
|
165
|
-
throw new Error(
|
|
166
|
-
`CurseForge API returned unexpected response: ${JSON.stringify(response.data)}`
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
} catch (error: any) {
|
|
170
|
-
if (error.response) {
|
|
171
|
-
// 服务器返回了错误响应
|
|
172
|
-
const status = error.response.status;
|
|
173
|
-
const data = error.response.data;
|
|
174
|
-
|
|
175
|
-
if (data && data.error && data.description) {
|
|
176
|
-
logger.error(
|
|
177
|
-
`CurseForge API Error (${status}): ${data.error} - ${data.description}`
|
|
178
|
-
);
|
|
179
|
-
throw new Error(
|
|
180
|
-
`CurseForge 发布失败:${data.error} - ${data.description}`
|
|
181
|
-
);
|
|
182
|
-
} else {
|
|
183
|
-
logger.error(
|
|
184
|
-
`CurseForge API Error (${status}): ${JSON.stringify(data)}`
|
|
185
|
-
);
|
|
186
|
-
throw new Error(
|
|
187
|
-
`CurseForge 发布失败 (状态码:${status}): ${JSON.stringify(data)}`
|
|
188
|
-
);
|
|
189
|
-
}
|
|
190
|
-
} else if (error.request) {
|
|
191
|
-
// 请求已发送但未收到响应
|
|
192
|
-
logger.error('CurseForge API 请求失败,未收到响应');
|
|
193
|
-
throw new Error('CurseForge 发布失败:未收到服务器响应');
|
|
194
|
-
} else {
|
|
195
|
-
// 请求配置出错
|
|
196
|
-
logger.error('CurseForge API 请求配置错误:', error.message);
|
|
197
|
-
throw new Error(`CurseForge 发布失败:${error.message}`);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
137
|
+
return metadata;
|
|
200
138
|
}
|
|
@@ -14,32 +14,32 @@ export interface CurseForgeGameVersionType {
|
|
|
14
14
|
|
|
15
15
|
export interface CurseForgeGameVersionMap {
|
|
16
16
|
/**
|
|
17
|
-
* Minecraft
|
|
17
|
+
* Array of Minecraft game versions.
|
|
18
18
|
*/
|
|
19
19
|
game_versions: CurseForgeGameVersion[];
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
22
|
+
* Array of game versions primarily used for Bukkit plugins.
|
|
23
23
|
*/
|
|
24
24
|
game_versions_for_plugins: CurseForgeGameVersion[];
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
27
|
+
* Array of game versions for add-ons.
|
|
28
28
|
*/
|
|
29
29
|
game_versions_for_addons: CurseForgeGameVersion[];
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
|
-
* Java
|
|
32
|
+
* Array of Java versions.
|
|
33
33
|
*/
|
|
34
34
|
java_versions: CurseForgeGameVersion[];
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
37
|
+
* Array of game versions for mod loaders.
|
|
38
38
|
*/
|
|
39
39
|
loaders: CurseForgeGameVersion[];
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
42
|
+
* Array of game versions for different environments.
|
|
43
43
|
*/
|
|
44
44
|
environments: CurseForgeGameVersion[];
|
|
45
45
|
}
|