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.
Files changed (58) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/curseforge.d.ts +2 -2
  3. package/dist/curseforge.d.ts.map +1 -1
  4. package/dist/curseforge.js +47 -115
  5. package/dist/curseforge.js.map +1 -1
  6. package/dist/definitions/curseforge.d.ts +6 -6
  7. package/dist/definitions/{plugin_config.d.ts → plugin-config.d.ts} +4 -3
  8. package/dist/definitions/plugin-config.d.ts.map +1 -0
  9. package/dist/definitions/plugin-config.js +2 -0
  10. package/dist/definitions/plugin-config.js.map +1 -0
  11. package/dist/index.d.ts +4 -4
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +12 -23
  14. package/dist/index.js.map +1 -1
  15. package/dist/modrinth.d.ts +3 -3
  16. package/dist/modrinth.d.ts.map +1 -1
  17. package/dist/modrinth.js +58 -223
  18. package/dist/modrinth.js.map +1 -1
  19. package/dist/prepare.d.ts +4 -8
  20. package/dist/prepare.d.ts.map +1 -1
  21. package/dist/prepare.js +31 -32
  22. package/dist/prepare.js.map +1 -1
  23. package/dist/utils/glob-utils.d.ts +6 -0
  24. package/dist/utils/glob-utils.d.ts.map +1 -0
  25. package/dist/utils/glob-utils.js +27 -0
  26. package/dist/utils/glob-utils.js.map +1 -0
  27. package/dist/utils/platform/curseforge-utils.d.ts +4 -0
  28. package/dist/utils/platform/curseforge-utils.d.ts.map +1 -0
  29. package/dist/utils/platform/curseforge-utils.js +7 -0
  30. package/dist/utils/platform/curseforge-utils.js.map +1 -0
  31. package/dist/utils/platform/utils.d.ts +10 -0
  32. package/dist/utils/platform/utils.d.ts.map +1 -0
  33. package/dist/utils/platform/utils.js +56 -0
  34. package/dist/utils/platform/utils.js.map +1 -0
  35. package/dist/utils/template-utils.d.ts +26 -0
  36. package/dist/utils/template-utils.d.ts.map +1 -0
  37. package/dist/utils/template-utils.js +40 -0
  38. package/dist/utils/template-utils.js.map +1 -0
  39. package/dist/utils/utils.d.ts +4 -26
  40. package/dist/utils/utils.d.ts.map +1 -1
  41. package/dist/utils/utils.js +5 -79
  42. package/dist/utils/utils.js.map +1 -1
  43. package/package.json +1 -1
  44. package/src/curseforge.ts +98 -160
  45. package/src/definitions/curseforge.ts +6 -6
  46. package/src/definitions/plugin-config.ts +68 -0
  47. package/src/index.ts +28 -34
  48. package/src/modrinth.ts +78 -271
  49. package/src/prepare.ts +43 -52
  50. package/src/utils/glob-utils.ts +38 -0
  51. package/src/utils/platform/curseforge-utils.ts +17 -0
  52. package/src/utils/platform/utils.ts +84 -0
  53. package/src/utils/template-utils.ts +54 -0
  54. package/src/utils/utils.ts +5 -115
  55. package/dist/definitions/plugin_config.d.ts.map +0 -1
  56. package/dist/definitions/plugin_config.js +0 -2
  57. package/dist/definitions/plugin_config.js.map +0 -1
  58. 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"}
@@ -1,30 +1,8 @@
1
- import { NextRelease, PublishContext } from 'semantic-release';
2
- import { Plugin_config } from '../definitions/plugin_config.js';
3
1
  /**
4
- * 根据 glob 模式查找文件
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":"AAGA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAEhE;;GAEG;AACH,wBAAsB,SAAS,CAC3B,QAAQ,EAAE,MAAM,EAAE,YAGjB,EACD,OAAO,EAAE,cAAc,GACxB,OAAO,CAAC,MAAM,EAAE,CAAC,CAwBnB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC3B,SAAS,EAAE,MAAM,EAAE,EACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC7B,MAAM,EAAE,CAEV;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC3B,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,wBAAgB,uBAAuB,CACnC,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;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,CAE9C;AAED,wBAAgB,uBAAuB,CACnC,YAAY,EAAE,aAAa,EAC3B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,WAAW,EAAE,WAAW,GACzB,MAAM,EAAE,CAsBV"}
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"}
@@ -1,86 +1,12 @@
1
- import { glob } from 'glob';
2
- import _ from 'lodash';
3
- import { resolve } from 'path';
4
1
  /**
5
- * 根据 glob 模式查找文件
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
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"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"}
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "semantic-release-minecraft",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "description": "Automated Release For Minecraft Project",
5
5
  "keywords": [
6
6
  "semantic-release",
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 { Plugin_config } from './definitions/plugin_config.js';
6
- import {
7
- findFiles,
8
- getCurseForgeModLoaders,
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
- const files = await findFiles(curseforgeGlob, context);
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
- `Found ${files.length} files for CurseForge, trying to filter by version`
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
- if (version) {
50
- const versionedFiles = files.filter((file) => file.includes(version));
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
- export async function publishToCurseforge(
70
- pluginConfig: Plugin_config,
55
+ async function uploadCurseForgeFile(
56
+ pluginConfig: PluginConfig,
71
57
  context: PublishContext,
72
- curseforgeGameVersionIds?: number[]
73
- ): Promise<string> {
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.split('\\').pop() || 'mod.jar',
71
+ filename: basename(filePath),
90
72
  });
91
73
 
92
- // 准备 metadata
93
- // display_name 按照优先级:平台特定配置 > 全局配置 > 平台特定环境变量 > 全局环境变量
94
- const displayName = resolveTemplate(
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
- // 准备基础 metadata
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
- // 只有找到值时才添加 displayName
113
- if (displayName) {
114
- metadata.displayName = displayName;
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
- if (curseforge?.is_marked_for_manual_release !== undefined) {
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
- form.append('metadata', JSON.stringify(metadata));
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
- // 验证返回的数据是否包含 id 字段
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
- * 主要用于 Bukkit 插件的游戏版本数组。
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
  }