backlog-exporter 0.5.1 → 0.6.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/LICENSE +21 -0
- package/README.md +39 -7
- package/dist/utils/backlog-api.d.ts +29 -0
- package/dist/utils/backlog-api.js +59 -1
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 ShuntaToda
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ Backlog のデータをエクスポートするためのコマンドラインツ
|
|
|
52
52
|
backlog-exporter は、Backlog のデータをローカルにエクスポートするためのコマンドラインツールです。
|
|
53
53
|
現在、以下の機能をサポートしています:
|
|
54
54
|
|
|
55
|
-
- **課題(Issue)のエクスポート**:Backlog の課題を Markdown
|
|
55
|
+
- **課題(Issue)のエクスポート**:Backlog の課題を Markdown ファイルとして保存(カスタム属性対応)
|
|
56
56
|
- **Wiki 記事のエクスポート**:Backlog の Wiki 記事を Markdown ファイルとして保存
|
|
57
57
|
- **ドキュメントのエクスポート**:Backlog のドキュメントを Markdown ファイルとして保存
|
|
58
58
|
- **一括エクスポート**:課題・Wiki・ドキュメントを同時に取得する機能
|
|
@@ -66,7 +66,7 @@ $ npm install -g backlog-exporter
|
|
|
66
66
|
$ backlog-exporter COMMAND
|
|
67
67
|
running command...
|
|
68
68
|
$ backlog-exporter (--version)
|
|
69
|
-
backlog-exporter/0.
|
|
69
|
+
backlog-exporter/0.6.0 linux-x64 node-v24.2.0
|
|
70
70
|
$ backlog-exporter --help [COMMAND]
|
|
71
71
|
USAGE
|
|
72
72
|
$ backlog-exporter COMMAND
|
|
@@ -127,6 +127,28 @@ $ backlog-exporter issue --domain example.backlog.jp --projectIdOrKey PROJECT_KE
|
|
|
127
127
|
|
|
128
128
|
エクスポートされた課題は、指定したディレクトリ内に Markdown ファイルとして保存されます。ファイル名は課題のキーに基づいて自動的に生成されます。
|
|
129
129
|
|
|
130
|
+
## カスタム属性の対応
|
|
131
|
+
|
|
132
|
+
課題のエクスポートでは、Backlogのカスタム属性も含めて出力されます:
|
|
133
|
+
|
|
134
|
+
### 対応している値の型
|
|
135
|
+
- **プリミティブ値**: 文字列、数値などの単純な値
|
|
136
|
+
- **配列値**: 複数選択のカスタム属性(カンマ区切りで表示)
|
|
137
|
+
- **オブジェクト値**: 単一選択のカスタム属性(name または value プロパティを使用)
|
|
138
|
+
|
|
139
|
+
### 表示形式
|
|
140
|
+
カスタム属性はMarkdownテーブル形式で表示され、改行やパイプ文字も適切に処理されます:
|
|
141
|
+
|
|
142
|
+
```markdown
|
|
143
|
+
## カスタム属性
|
|
144
|
+
|
|
145
|
+
| 属性名 | 値 |
|
|
146
|
+
|--------|----|
|
|
147
|
+
| 工数(エンジニア) | 3 |
|
|
148
|
+
| 担当チーム | フロントエンド, バックエンド |
|
|
149
|
+
| 詳細 | 実装内容<br>- 機能A<br>- 機能B |
|
|
150
|
+
```
|
|
151
|
+
|
|
130
152
|
# Wiki のエクスポート
|
|
131
153
|
|
|
132
154
|
`wiki`コマンドを使用すると、Backlog の Wiki ページを Markdown ファイルとしてエクスポートできます。
|
|
@@ -281,7 +303,7 @@ EXAMPLES
|
|
|
281
303
|
最大1000件の課題を取得する(デフォルトは5000件)
|
|
282
304
|
```
|
|
283
305
|
|
|
284
|
-
_See code: [src/commands/all/index.ts](https://github.com/ShuntaToda/backlog-exporter/blob/v0.
|
|
306
|
+
_See code: [src/commands/all/index.ts](https://github.com/ShuntaToda/backlog-exporter/blob/v0.6.0/src/commands/all/index.ts)_
|
|
285
307
|
|
|
286
308
|
## `backlog-exporter document`
|
|
287
309
|
|
|
@@ -313,7 +335,7 @@ EXAMPLES
|
|
|
313
335
|
キーワード「仕様書」を含むドキュメントのみを取得する
|
|
314
336
|
```
|
|
315
337
|
|
|
316
|
-
_See code: [src/commands/document/index.ts](https://github.com/ShuntaToda/backlog-exporter/blob/v0.
|
|
338
|
+
_See code: [src/commands/document/index.ts](https://github.com/ShuntaToda/backlog-exporter/blob/v0.6.0/src/commands/document/index.ts)_
|
|
317
339
|
|
|
318
340
|
## `backlog-exporter help [COMMAND]`
|
|
319
341
|
|
|
@@ -369,7 +391,7 @@ EXAMPLES
|
|
|
369
391
|
最大10000件の課題を取得する(デフォルトは5000件)
|
|
370
392
|
```
|
|
371
393
|
|
|
372
|
-
_See code: [src/commands/issue/index.ts](https://github.com/ShuntaToda/backlog-exporter/blob/v0.
|
|
394
|
+
_See code: [src/commands/issue/index.ts](https://github.com/ShuntaToda/backlog-exporter/blob/v0.6.0/src/commands/issue/index.ts)_
|
|
373
395
|
|
|
374
396
|
## `backlog-exporter plugins`
|
|
375
397
|
|
|
@@ -699,7 +721,7 @@ EXAMPLES
|
|
|
699
721
|
指定したディレクトリの設定を使用して更新する
|
|
700
722
|
```
|
|
701
723
|
|
|
702
|
-
_See code: [src/commands/update/index.ts](https://github.com/ShuntaToda/backlog-exporter/blob/v0.
|
|
724
|
+
_See code: [src/commands/update/index.ts](https://github.com/ShuntaToda/backlog-exporter/blob/v0.6.0/src/commands/update/index.ts)_
|
|
703
725
|
|
|
704
726
|
## `backlog-exporter wiki`
|
|
705
727
|
|
|
@@ -726,7 +748,7 @@ EXAMPLES
|
|
|
726
748
|
指定したディレクトリにWikiを保存する
|
|
727
749
|
```
|
|
728
750
|
|
|
729
|
-
_See code: [src/commands/wiki/index.ts](https://github.com/ShuntaToda/backlog-exporter/blob/v0.
|
|
751
|
+
_See code: [src/commands/wiki/index.ts](https://github.com/ShuntaToda/backlog-exporter/blob/v0.6.0/src/commands/wiki/index.ts)_
|
|
730
752
|
<!-- commandsstop -->
|
|
731
753
|
|
|
732
754
|
# 出力形式
|
|
@@ -748,6 +770,15 @@ _See code: [src/commands/wiki/index.ts](https://github.com/ShuntaToda/backlog-ex
|
|
|
748
770
|
- 更新日時: 2023/01/02 15:30:45
|
|
749
771
|
- [Backlog Issue Link](https://example.backlog.jp/view/PROJ-123)
|
|
750
772
|
|
|
773
|
+
## カスタム属性
|
|
774
|
+
|
|
775
|
+
| 属性名 | 値 |
|
|
776
|
+
|--------|----|
|
|
777
|
+
| 工数(エンジニア) | 3 |
|
|
778
|
+
| 工数(PPO) | なし |
|
|
779
|
+
| 担当チーム | フロントエンド, バックエンド |
|
|
780
|
+
| 詳細 | 実装内容<br>- 機能A<br>- 機能B |
|
|
781
|
+
|
|
751
782
|
## 詳細
|
|
752
783
|
|
|
753
784
|
ここに課題の詳細説明が入ります。
|
|
@@ -822,3 +853,4 @@ Backlog の書式がそのまま保持されます。
|
|
|
822
853
|
- **階層構造の保持**: Wiki の階層構造を保持したエクスポート
|
|
823
854
|
- **キーワード検索**: ドキュメントの検索キーワード対応
|
|
824
855
|
- **差分更新**: 前回の更新以降に変更されたデータのみを更新
|
|
856
|
+
- **カスタム属性対応**: 課題のカスタム属性をテーブル形式で表示(配列・オブジェクト・プリミティブ値に対応)
|
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
+
/**
|
|
3
|
+
* カスタム属性セクションを作成する
|
|
4
|
+
* @param customFields カスタム属性の配列
|
|
5
|
+
* @returns Markdownテーブル形式のカスタム属性セクション
|
|
6
|
+
*/
|
|
7
|
+
export declare function createCustomFieldsSection(customFields?: Array<{
|
|
8
|
+
id: number;
|
|
9
|
+
name: string;
|
|
10
|
+
value: unknown;
|
|
11
|
+
}>): string;
|
|
2
12
|
/**
|
|
3
13
|
* Backlogから課題をダウンロードする
|
|
4
14
|
* @param command コマンドインスタンス
|
|
5
15
|
* @param options 課題ダウンロードのオプション
|
|
16
|
+
* @param options.apiKey Backlog API key
|
|
17
|
+
* @param options.count 取得する課題の最大数
|
|
18
|
+
* @param options.domain Backlogのドメイン
|
|
19
|
+
* @param options.lastUpdated 最終更新日時
|
|
20
|
+
* @param options.outputDir 出力ディレクトリ
|
|
21
|
+
* @param options.projectId プロジェクトID
|
|
22
|
+
* @param options.statusId ステータスID
|
|
6
23
|
*/
|
|
7
24
|
export declare function downloadIssues(command: Command, options: {
|
|
8
25
|
apiKey: string;
|
|
@@ -17,6 +34,11 @@ export declare function downloadIssues(command: Command, options: {
|
|
|
17
34
|
* BacklogからWikiをダウンロードする
|
|
18
35
|
* @param command コマンドインスタンス
|
|
19
36
|
* @param options Wikiダウンロードのオプション
|
|
37
|
+
* @param options.apiKey Backlog API key
|
|
38
|
+
* @param options.domain Backlogのドメイン
|
|
39
|
+
* @param options.lastUpdated 最終更新日時
|
|
40
|
+
* @param options.outputDir 出力ディレクトリ
|
|
41
|
+
* @param options.projectIdOrKey プロジェクトIDまたはキー
|
|
20
42
|
*/
|
|
21
43
|
export declare function downloadWikis(command: Command, options: {
|
|
22
44
|
apiKey: string;
|
|
@@ -29,6 +51,13 @@ export declare function downloadWikis(command: Command, options: {
|
|
|
29
51
|
* Backlogからドキュメントをダウンロードする
|
|
30
52
|
* @param command コマンドインスタンス
|
|
31
53
|
* @param options ドキュメントダウンロードのオプション
|
|
54
|
+
* @param options.apiKey Backlog API key
|
|
55
|
+
* @param options.domain Backlogのドメイン
|
|
56
|
+
* @param options.keyword キーワードフィルター
|
|
57
|
+
* @param options.lastUpdated 最終更新日時
|
|
58
|
+
* @param options.outputDir 出力ディレクトリ
|
|
59
|
+
* @param options.projectId プロジェクトID
|
|
60
|
+
* @param options.projectIdOrKey プロジェクトIDまたはキー
|
|
32
61
|
*/
|
|
33
62
|
export declare function downloadDocuments(command: Command, options: {
|
|
34
63
|
apiKey: string;
|
|
@@ -5,10 +5,54 @@ import process from 'node:process';
|
|
|
5
5
|
import { sanitizeFileName, sanitizeWikiFileName } from './common.js';
|
|
6
6
|
import { appendLog } from './log.js';
|
|
7
7
|
import { RateLimiter } from './sleep.js';
|
|
8
|
+
/**
|
|
9
|
+
* カスタム属性セクションを作成する
|
|
10
|
+
* @param customFields カスタム属性の配列
|
|
11
|
+
* @returns Markdownテーブル形式のカスタム属性セクション
|
|
12
|
+
*/
|
|
13
|
+
export function createCustomFieldsSection(customFields) {
|
|
14
|
+
if (!customFields || customFields.length === 0) {
|
|
15
|
+
return '';
|
|
16
|
+
}
|
|
17
|
+
let customFieldsSection = '\n\n## カスタム属性\n\n| 属性名 | 値 |\n|--------|----|\n';
|
|
18
|
+
for (const customField of customFields) {
|
|
19
|
+
let fieldValue = 'なし';
|
|
20
|
+
if (customField.value !== null && customField.value !== undefined) {
|
|
21
|
+
if (Array.isArray(customField.value)) {
|
|
22
|
+
// 配列の場合(複数選択など)
|
|
23
|
+
fieldValue = customField.value
|
|
24
|
+
.map(item => item.name || item.value || String(item))
|
|
25
|
+
.join(', ');
|
|
26
|
+
}
|
|
27
|
+
else if (typeof customField.value === 'object' && customField.value !== null) {
|
|
28
|
+
// オブジェクトの場合(単一選択など)
|
|
29
|
+
const valueObj = customField.value;
|
|
30
|
+
fieldValue = valueObj.name || valueObj.value || String(customField.value);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
// プリミティブ値の場合
|
|
34
|
+
fieldValue = String(customField.value);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// テーブル内では改行をHTMLの<br>タグに変換し、パイプ文字をエスケープ
|
|
38
|
+
const escapedFieldValue = fieldValue
|
|
39
|
+
.replaceAll('|', String.raw `\|`)
|
|
40
|
+
.replaceAll('\n', '<br>');
|
|
41
|
+
customFieldsSection += `| ${customField.name} | ${escapedFieldValue} |\n`;
|
|
42
|
+
}
|
|
43
|
+
return customFieldsSection;
|
|
44
|
+
}
|
|
8
45
|
/**
|
|
9
46
|
* Backlogから課題をダウンロードする
|
|
10
47
|
* @param command コマンドインスタンス
|
|
11
48
|
* @param options 課題ダウンロードのオプション
|
|
49
|
+
* @param options.apiKey Backlog API key
|
|
50
|
+
* @param options.count 取得する課題の最大数
|
|
51
|
+
* @param options.domain Backlogのドメイン
|
|
52
|
+
* @param options.lastUpdated 最終更新日時
|
|
53
|
+
* @param options.outputDir 出力ディレクトリ
|
|
54
|
+
* @param options.projectId プロジェクトID
|
|
55
|
+
* @param options.statusId ステータスID
|
|
12
56
|
*/
|
|
13
57
|
export async function downloadIssues(command, options) {
|
|
14
58
|
const baseUrl = `https://${options.domain}/api/v2`;
|
|
@@ -114,6 +158,8 @@ export async function downloadIssues(command, options) {
|
|
|
114
158
|
// 年ごとのフォルダ内にMarkdownファイルを保存
|
|
115
159
|
const issueFileName = `${sanitizeFileName(issue.summary)}.md`;
|
|
116
160
|
const issueFilePath = path.join(yearDirPath, issueFileName);
|
|
161
|
+
// カスタム属性セクションを作成
|
|
162
|
+
const customFieldsSection = createCustomFieldsSection(issue.customFields);
|
|
117
163
|
// Markdownファイルに書き込む
|
|
118
164
|
const assigneeName = issue.assignee ? issue.assignee.name : '未割り当て';
|
|
119
165
|
const markdownContent = `# ${issue.summary}
|
|
@@ -125,7 +171,7 @@ export async function downloadIssues(command, options) {
|
|
|
125
171
|
- 担当者: ${assigneeName}
|
|
126
172
|
- 作成日時: ${new Date(issue.created).toLocaleString('ja-JP')}
|
|
127
173
|
- 更新日時: ${new Date(issue.updated).toLocaleString('ja-JP')}
|
|
128
|
-
- [Backlog Issue Link](${backlogIssueUrl})
|
|
174
|
+
- [Backlog Issue Link](${backlogIssueUrl})${customFieldsSection}
|
|
129
175
|
|
|
130
176
|
## 詳細
|
|
131
177
|
${issue.description || '詳細情報なし'}${commentsSection}`;
|
|
@@ -176,6 +222,11 @@ async function fetchAllCommentsForIssue({ apiKey, baseUrl, command, issueKey, ra
|
|
|
176
222
|
* BacklogからWikiをダウンロードする
|
|
177
223
|
* @param command コマンドインスタンス
|
|
178
224
|
* @param options Wikiダウンロードのオプション
|
|
225
|
+
* @param options.apiKey Backlog API key
|
|
226
|
+
* @param options.domain Backlogのドメイン
|
|
227
|
+
* @param options.lastUpdated 最終更新日時
|
|
228
|
+
* @param options.outputDir 出力ディレクトリ
|
|
229
|
+
* @param options.projectIdOrKey プロジェクトIDまたはキー
|
|
179
230
|
*/
|
|
180
231
|
export async function downloadWikis(command, options) {
|
|
181
232
|
const baseUrl = `https://${options.domain}/api/v2`;
|
|
@@ -259,6 +310,13 @@ export async function downloadWikis(command, options) {
|
|
|
259
310
|
* Backlogからドキュメントをダウンロードする
|
|
260
311
|
* @param command コマンドインスタンス
|
|
261
312
|
* @param options ドキュメントダウンロードのオプション
|
|
313
|
+
* @param options.apiKey Backlog API key
|
|
314
|
+
* @param options.domain Backlogのドメイン
|
|
315
|
+
* @param options.keyword キーワードフィルター
|
|
316
|
+
* @param options.lastUpdated 最終更新日時
|
|
317
|
+
* @param options.outputDir 出力ディレクトリ
|
|
318
|
+
* @param options.projectId プロジェクトID
|
|
319
|
+
* @param options.projectIdOrKey プロジェクトIDまたはキー
|
|
262
320
|
*/
|
|
263
321
|
export async function downloadDocuments(command, options) {
|
|
264
322
|
const baseUrl = `https://${options.domain}/api/v2`;
|
package/oclif.manifest.json
CHANGED