@shuji-bonji/rfcxml-mcp 0.1.2 → 0.1.3
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/README.ja.md +66 -0
- package/README.md +60 -0
- package/dist/config.d.ts +91 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +93 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +15 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +29 -0
- package/dist/constants.js.map +1 -0
- package/dist/services/rfc-fetcher.d.ts +4 -2
- package/dist/services/rfc-fetcher.d.ts.map +1 -1
- package/dist/services/rfc-fetcher.js +56 -86
- package/dist/services/rfc-fetcher.js.map +1 -1
- package/dist/services/rfc-text-parser.d.ts.map +1 -1
- package/dist/services/rfc-text-parser.js +3 -55
- package/dist/services/rfc-text-parser.js.map +1 -1
- package/dist/services/rfcxml-parser.d.ts.map +1 -1
- package/dist/services/rfcxml-parser.js +2 -65
- package/dist/services/rfcxml-parser.js.map +1 -1
- package/dist/tools/handlers.d.ts.map +1 -1
- package/dist/tools/handlers.js +7 -2
- package/dist/tools/handlers.js.map +1 -1
- package/dist/utils/cache.d.ts +62 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +107 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/fetch.d.ts +28 -0
- package/dist/utils/fetch.d.ts.map +1 -0
- package/dist/utils/fetch.js +100 -0
- package/dist/utils/fetch.js.map +1 -0
- package/dist/utils/text.d.ts +26 -0
- package/dist/utils/text.d.ts.map +1 -0
- package/dist/utils/text.js +62 -0
- package/dist/utils/text.js.map +1 -0
- package/package.json +1 -1
package/README.ja.md
CHANGED
|
@@ -246,6 +246,66 @@ RFC 8650 (2019年12月) 以降は公式 RFCXML v3 形式で提供されていま
|
|
|
246
246
|
}
|
|
247
247
|
```
|
|
248
248
|
|
|
249
|
+
## 内部アーキテクチャ
|
|
250
|
+
|
|
251
|
+
### モジュール構成
|
|
252
|
+
|
|
253
|
+
```
|
|
254
|
+
src/
|
|
255
|
+
├── index.ts # MCP サーバーエントリポイント
|
|
256
|
+
├── config.ts # 設定の一元管理
|
|
257
|
+
├── constants.ts # BCP 14 キーワード定義
|
|
258
|
+
├── services/
|
|
259
|
+
│ ├── rfc-fetcher.ts # RFC 取得(並列フェッチ)
|
|
260
|
+
│ ├── rfcxml-parser.ts # RFCXML パーサー
|
|
261
|
+
│ └── rfc-text-parser.ts # テキストフォールバック
|
|
262
|
+
├── tools/
|
|
263
|
+
│ ├── definitions.ts # MCP ツール定義
|
|
264
|
+
│ └── handlers.ts # ツールハンドラー
|
|
265
|
+
├── types/
|
|
266
|
+
│ └── index.ts # 型定義
|
|
267
|
+
└── utils/
|
|
268
|
+
├── cache.ts # LRU キャッシュ
|
|
269
|
+
├── fetch.ts # 並列フェッチユーティリティ
|
|
270
|
+
└── text.ts # テキスト処理ユーティリティ
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### RFC 取得の最適化
|
|
274
|
+
|
|
275
|
+
複数ソース(RFC Editor、IETF Tools、Datatracker)に並列リクエストを送信し、最初に成功したレスポンスを採用:
|
|
276
|
+
|
|
277
|
+
```
|
|
278
|
+
┌─────────────────┐
|
|
279
|
+
│ fetchRFCXML() │
|
|
280
|
+
└────────┬────────┘
|
|
281
|
+
│ 並列リクエスト
|
|
282
|
+
┌────┴────┬────────────┐
|
|
283
|
+
▼ ▼ ▼
|
|
284
|
+
┌────────┐ ┌────────┐ ┌────────┐
|
|
285
|
+
│RFC │ │IETF │ │Data- │
|
|
286
|
+
│Editor │ │Tools │ │tracker │
|
|
287
|
+
└────┬───┘ └────┬───┘ └────┬───┘
|
|
288
|
+
│ │ │
|
|
289
|
+
└────┬─────┴──────────┘
|
|
290
|
+
│ Promise.any(最初の成功)
|
|
291
|
+
▼
|
|
292
|
+
┌───────────┐
|
|
293
|
+
│ 成功した │ → 他のリクエストを AbortController でキャンセル
|
|
294
|
+
│ レスポンス│
|
|
295
|
+
└───────────┘
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### キャッシュ戦略
|
|
299
|
+
|
|
300
|
+
LRU(Least Recently Used)キャッシュでメモリ使用量を制限:
|
|
301
|
+
|
|
302
|
+
| キャッシュ | 最大エントリ数 | 内容 |
|
|
303
|
+
|-----------|---------------|------|
|
|
304
|
+
| XML キャッシュ | 20 | 生の RFCXML |
|
|
305
|
+
| Text キャッシュ | 20 | 生のテキスト |
|
|
306
|
+
| Metadata キャッシュ | 100 | RFC メタデータ |
|
|
307
|
+
| Parse キャッシュ | 50 | パース済み構造 |
|
|
308
|
+
|
|
249
309
|
## 開発
|
|
250
310
|
|
|
251
311
|
```bash
|
|
@@ -260,6 +320,12 @@ npm run build
|
|
|
260
320
|
|
|
261
321
|
# テスト
|
|
262
322
|
npm test
|
|
323
|
+
|
|
324
|
+
# リント
|
|
325
|
+
npm run lint
|
|
326
|
+
|
|
327
|
+
# フォーマット
|
|
328
|
+
npm run format
|
|
263
329
|
```
|
|
264
330
|
|
|
265
331
|
## ライセンス
|
package/README.md
CHANGED
|
@@ -244,6 +244,66 @@ Role: Client
|
|
|
244
244
|
}
|
|
245
245
|
```
|
|
246
246
|
|
|
247
|
+
## Internal Architecture
|
|
248
|
+
|
|
249
|
+
### Module Structure
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
src/
|
|
253
|
+
├── index.ts # MCP server entry point
|
|
254
|
+
├── config.ts # Centralized configuration
|
|
255
|
+
├── constants.ts # BCP 14 keyword definitions
|
|
256
|
+
├── services/
|
|
257
|
+
│ ├── rfc-fetcher.ts # RFC fetching (parallel)
|
|
258
|
+
│ ├── rfcxml-parser.ts # RFCXML parser
|
|
259
|
+
│ └── rfc-text-parser.ts # Text fallback parser
|
|
260
|
+
├── tools/
|
|
261
|
+
│ ├── definitions.ts # MCP tool definitions
|
|
262
|
+
│ └── handlers.ts # Tool handlers
|
|
263
|
+
├── types/
|
|
264
|
+
│ └── index.ts # Type definitions
|
|
265
|
+
└── utils/
|
|
266
|
+
├── cache.ts # LRU cache
|
|
267
|
+
├── fetch.ts # Parallel fetch utility
|
|
268
|
+
└── text.ts # Text processing utility
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### RFC Fetch Optimization
|
|
272
|
+
|
|
273
|
+
Sends parallel requests to multiple sources (RFC Editor, IETF Tools, Datatracker) and uses the first successful response:
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
┌─────────────────┐
|
|
277
|
+
│ fetchRFCXML() │
|
|
278
|
+
└────────┬────────┘
|
|
279
|
+
│ Parallel requests
|
|
280
|
+
┌────┴────┬────────────┐
|
|
281
|
+
▼ ▼ ▼
|
|
282
|
+
┌────────┐ ┌────────┐ ┌────────┐
|
|
283
|
+
│RFC │ │IETF │ │Data- │
|
|
284
|
+
│Editor │ │Tools │ │tracker │
|
|
285
|
+
└────┬───┘ └────┬───┘ └────┬───┘
|
|
286
|
+
│ │ │
|
|
287
|
+
└────┬─────┴──────────┘
|
|
288
|
+
│ Promise.any (first success)
|
|
289
|
+
▼
|
|
290
|
+
┌───────────┐
|
|
291
|
+
│ Successful│ → Cancel other requests via AbortController
|
|
292
|
+
│ Response │
|
|
293
|
+
└───────────┘
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Cache Strategy
|
|
297
|
+
|
|
298
|
+
LRU (Least Recently Used) cache with memory limits:
|
|
299
|
+
|
|
300
|
+
| Cache | Max Entries | Content |
|
|
301
|
+
|-------|-------------|---------|
|
|
302
|
+
| XML Cache | 20 | Raw RFCXML |
|
|
303
|
+
| Text Cache | 20 | Raw text |
|
|
304
|
+
| Metadata Cache | 100 | RFC metadata |
|
|
305
|
+
| Parse Cache | 50 | Parsed structure |
|
|
306
|
+
|
|
247
307
|
## Development
|
|
248
308
|
|
|
249
309
|
```bash
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* アプリケーション設定
|
|
3
|
+
* すべての設定値を一箇所で管理
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* パッケージ情報
|
|
7
|
+
*/
|
|
8
|
+
export declare const PACKAGE_INFO: {
|
|
9
|
+
readonly name: "rfcxml-mcp";
|
|
10
|
+
readonly version: "0.1.2";
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* HTTP リクエスト設定
|
|
14
|
+
*/
|
|
15
|
+
export declare const HTTP_CONFIG: {
|
|
16
|
+
/** User-Agent ヘッダー */
|
|
17
|
+
readonly userAgent: "rfcxml-mcp/0.1.2";
|
|
18
|
+
/** タイムアウト(ミリ秒) */
|
|
19
|
+
readonly timeout: 30000;
|
|
20
|
+
/** リトライ回数 */
|
|
21
|
+
readonly maxRetries: 3;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* キャッシュ設定
|
|
25
|
+
*/
|
|
26
|
+
export declare const CACHE_CONFIG: {
|
|
27
|
+
/** XML 生データキャッシュ(小さめ:パース済みがメイン) */
|
|
28
|
+
readonly xml: {
|
|
29
|
+
readonly maxSize: 20;
|
|
30
|
+
readonly name: "XMLCache";
|
|
31
|
+
};
|
|
32
|
+
/** テキスト生データキャッシュ */
|
|
33
|
+
readonly text: {
|
|
34
|
+
readonly maxSize: 20;
|
|
35
|
+
readonly name: "TextCache";
|
|
36
|
+
};
|
|
37
|
+
/** メタデータキャッシュ(軽量なので多め) */
|
|
38
|
+
readonly metadata: {
|
|
39
|
+
readonly maxSize: 100;
|
|
40
|
+
readonly name: "MetadataCache";
|
|
41
|
+
};
|
|
42
|
+
/** パース済み RFC キャッシュ(メインキャッシュ) */
|
|
43
|
+
readonly parsed: {
|
|
44
|
+
readonly maxSize: 50;
|
|
45
|
+
readonly name: "ParseCache";
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* RFC 関連の設定
|
|
50
|
+
*/
|
|
51
|
+
export declare const RFC_CONFIG: {
|
|
52
|
+
/**
|
|
53
|
+
* RFCXML v3 が確実に利用可能な最小 RFC 番号
|
|
54
|
+
* RFC 8650 (2019年12月) 以降は公式に RFCXML v3 形式
|
|
55
|
+
*/
|
|
56
|
+
readonly xmlAvailableFrom: 8650;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* RFC XML ソースの取得元
|
|
60
|
+
* 優先順位順に定義
|
|
61
|
+
*/
|
|
62
|
+
export declare const RFC_XML_SOURCES: {
|
|
63
|
+
/** RFC Editor 公式 */
|
|
64
|
+
readonly rfcEditor: (num: number) => string;
|
|
65
|
+
/** IETF Tools */
|
|
66
|
+
readonly ietfTools: (num: number) => string;
|
|
67
|
+
/** Datatracker */
|
|
68
|
+
readonly datatracker: (num: number) => string;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* RFC テキストソースの取得元
|
|
72
|
+
* 優先順位順に定義
|
|
73
|
+
*/
|
|
74
|
+
export declare const RFC_TEXT_SOURCES: {
|
|
75
|
+
/** RFC Editor 公式(テキスト) */
|
|
76
|
+
readonly rfcEditor: (num: number) => string;
|
|
77
|
+
/** IETF Tools */
|
|
78
|
+
readonly ietfTools: (num: number) => string;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* IETF Datatracker API
|
|
82
|
+
*/
|
|
83
|
+
export declare const DATATRACKER_API: {
|
|
84
|
+
/** RFC ドキュメント情報 */
|
|
85
|
+
readonly document: (num: number) => string;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* RFC が XML 形式で利用可能か確認
|
|
89
|
+
*/
|
|
90
|
+
export declare function isRFCXMLLikelyAvailable(rfcNumber: number): boolean;
|
|
91
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,WAAW;IACtB,sBAAsB;;IAEtB,kBAAkB;;IAElB,aAAa;;CAEL,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,YAAY;IACvB,mCAAmC;;;;;IAKnC,oBAAoB;;;;;IAKpB,0BAA0B;;;;;IAK1B,gCAAgC;;;;;CAKxB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,UAAU;IACrB;;;OAGG;;CAEK,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,eAAe;IAC1B,oBAAoB;8BACH,MAAM;IACvB,iBAAiB;8BACA,MAAM;IACvB,kBAAkB;gCACC,MAAM;CACjB,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,gBAAgB;IAC3B,0BAA0B;8BACT,MAAM;IACvB,iBAAiB;8BACA,MAAM;CACf,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,eAAe;IAC1B,mBAAmB;6BACH,MAAM;CACd,CAAC;AAEX;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAElE"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* アプリケーション設定
|
|
3
|
+
* すべての設定値を一箇所で管理
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* パッケージ情報
|
|
7
|
+
*/
|
|
8
|
+
export const PACKAGE_INFO = {
|
|
9
|
+
name: 'rfcxml-mcp',
|
|
10
|
+
version: '0.1.2',
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* HTTP リクエスト設定
|
|
14
|
+
*/
|
|
15
|
+
export const HTTP_CONFIG = {
|
|
16
|
+
/** User-Agent ヘッダー */
|
|
17
|
+
userAgent: `${PACKAGE_INFO.name}/${PACKAGE_INFO.version}`,
|
|
18
|
+
/** タイムアウト(ミリ秒) */
|
|
19
|
+
timeout: 30000,
|
|
20
|
+
/** リトライ回数 */
|
|
21
|
+
maxRetries: 3,
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* キャッシュ設定
|
|
25
|
+
*/
|
|
26
|
+
export const CACHE_CONFIG = {
|
|
27
|
+
/** XML 生データキャッシュ(小さめ:パース済みがメイン) */
|
|
28
|
+
xml: {
|
|
29
|
+
maxSize: 20,
|
|
30
|
+
name: 'XMLCache',
|
|
31
|
+
},
|
|
32
|
+
/** テキスト生データキャッシュ */
|
|
33
|
+
text: {
|
|
34
|
+
maxSize: 20,
|
|
35
|
+
name: 'TextCache',
|
|
36
|
+
},
|
|
37
|
+
/** メタデータキャッシュ(軽量なので多め) */
|
|
38
|
+
metadata: {
|
|
39
|
+
maxSize: 100,
|
|
40
|
+
name: 'MetadataCache',
|
|
41
|
+
},
|
|
42
|
+
/** パース済み RFC キャッシュ(メインキャッシュ) */
|
|
43
|
+
parsed: {
|
|
44
|
+
maxSize: 50,
|
|
45
|
+
name: 'ParseCache',
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* RFC 関連の設定
|
|
50
|
+
*/
|
|
51
|
+
export const RFC_CONFIG = {
|
|
52
|
+
/**
|
|
53
|
+
* RFCXML v3 が確実に利用可能な最小 RFC 番号
|
|
54
|
+
* RFC 8650 (2019年12月) 以降は公式に RFCXML v3 形式
|
|
55
|
+
*/
|
|
56
|
+
xmlAvailableFrom: 8650,
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* RFC XML ソースの取得元
|
|
60
|
+
* 優先順位順に定義
|
|
61
|
+
*/
|
|
62
|
+
export const RFC_XML_SOURCES = {
|
|
63
|
+
/** RFC Editor 公式 */
|
|
64
|
+
rfcEditor: (num) => `https://www.rfc-editor.org/rfc/rfc${num}.xml`,
|
|
65
|
+
/** IETF Tools */
|
|
66
|
+
ietfTools: (num) => `https://xml2rfc.ietf.org/public/rfc/rfc${num}.xml`,
|
|
67
|
+
/** Datatracker */
|
|
68
|
+
datatracker: (num) => `https://datatracker.ietf.org/doc/rfc${num}/xml/`,
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* RFC テキストソースの取得元
|
|
72
|
+
* 優先順位順に定義
|
|
73
|
+
*/
|
|
74
|
+
export const RFC_TEXT_SOURCES = {
|
|
75
|
+
/** RFC Editor 公式(テキスト) */
|
|
76
|
+
rfcEditor: (num) => `https://www.rfc-editor.org/rfc/rfc${num}.txt`,
|
|
77
|
+
/** IETF Tools */
|
|
78
|
+
ietfTools: (num) => `https://tools.ietf.org/rfc/rfc${num}.txt`,
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* IETF Datatracker API
|
|
82
|
+
*/
|
|
83
|
+
export const DATATRACKER_API = {
|
|
84
|
+
/** RFC ドキュメント情報 */
|
|
85
|
+
document: (num) => `https://datatracker.ietf.org/api/v1/doc/document/rfc${num}/`,
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* RFC が XML 形式で利用可能か確認
|
|
89
|
+
*/
|
|
90
|
+
export function isRFCXMLLikelyAvailable(rfcNumber) {
|
|
91
|
+
return rfcNumber >= RFC_CONFIG.xmlAvailableFrom;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE,YAAY;IAClB,OAAO,EAAE,OAAO;CACR,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,sBAAsB;IACtB,SAAS,EAAE,GAAG,YAAY,CAAC,IAAI,IAAI,YAAY,CAAC,OAAO,EAAE;IACzD,kBAAkB;IAClB,OAAO,EAAE,KAAK;IACd,aAAa;IACb,UAAU,EAAE,CAAC;CACL,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,mCAAmC;IACnC,GAAG,EAAE;QACH,OAAO,EAAE,EAAE;QACX,IAAI,EAAE,UAAU;KACjB;IACD,oBAAoB;IACpB,IAAI,EAAE;QACJ,OAAO,EAAE,EAAE;QACX,IAAI,EAAE,WAAW;KAClB;IACD,0BAA0B;IAC1B,QAAQ,EAAE;QACR,OAAO,EAAE,GAAG;QACZ,IAAI,EAAE,eAAe;KACtB;IACD,gCAAgC;IAChC,MAAM,EAAE;QACN,OAAO,EAAE,EAAE;QACX,IAAI,EAAE,YAAY;KACnB;CACO,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB;;;OAGG;IACH,gBAAgB,EAAE,IAAI;CACd,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,oBAAoB;IACpB,SAAS,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,qCAAqC,GAAG,MAAM;IAC1E,iBAAiB;IACjB,SAAS,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,0CAA0C,GAAG,MAAM;IAC/E,kBAAkB;IAClB,WAAW,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,uCAAuC,GAAG,OAAO;CACvE,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,0BAA0B;IAC1B,SAAS,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,qCAAqC,GAAG,MAAM;IAC1E,iBAAiB;IACjB,SAAS,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,iCAAiC,GAAG,MAAM;CAC9D,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,mBAAmB;IACnB,QAAQ,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,uDAAuD,GAAG,GAAG;CAChF,CAAC;AAEX;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,SAAiB;IACvD,OAAO,SAAS,IAAI,UAAU,CAAC,gBAAgB,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 共通定数
|
|
3
|
+
* BCP 14 / RFC 2119 キーワードとパターン
|
|
4
|
+
*/
|
|
5
|
+
import type { RequirementLevel } from './types/index.js';
|
|
6
|
+
/**
|
|
7
|
+
* BCP 14 / RFC 2119 キーワード
|
|
8
|
+
* 長いキーワードから順に並べる("MUST NOT" を "MUST" より先にマッチさせるため)
|
|
9
|
+
*/
|
|
10
|
+
export declare const REQUIREMENT_KEYWORDS: RequirementLevel[];
|
|
11
|
+
/**
|
|
12
|
+
* キーワードの正規表現(長い順にマッチ)
|
|
13
|
+
*/
|
|
14
|
+
export declare const REQUIREMENT_REGEX: RegExp;
|
|
15
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,gBAAgB,EAYlD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAA+D,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 共通定数
|
|
3
|
+
* BCP 14 / RFC 2119 キーワードとパターン
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* BCP 14 / RFC 2119 キーワード
|
|
7
|
+
* 長いキーワードから順に並べる("MUST NOT" を "MUST" より先にマッチさせるため)
|
|
8
|
+
*/
|
|
9
|
+
export const REQUIREMENT_KEYWORDS = [
|
|
10
|
+
'MUST NOT',
|
|
11
|
+
'MUST',
|
|
12
|
+
'REQUIRED',
|
|
13
|
+
'SHALL NOT',
|
|
14
|
+
'SHALL',
|
|
15
|
+
'SHOULD NOT',
|
|
16
|
+
'SHOULD',
|
|
17
|
+
'RECOMMENDED',
|
|
18
|
+
'NOT RECOMMENDED',
|
|
19
|
+
'MAY',
|
|
20
|
+
'OPTIONAL',
|
|
21
|
+
];
|
|
22
|
+
/**
|
|
23
|
+
* キーワードの正規表現(長い順にマッチ)
|
|
24
|
+
*/
|
|
25
|
+
export const REQUIREMENT_REGEX = new RegExp(`\\b(${REQUIREMENT_KEYWORDS.join('|')})\\b`, 'g');
|
|
26
|
+
// RFC 関連の設定は config.ts に集約されています
|
|
27
|
+
// - RFC_CONFIG.xmlAvailableFrom
|
|
28
|
+
// - isRFCXMLLikelyAvailable()
|
|
29
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAuB;IACtD,UAAU;IACV,MAAM;IACN,UAAU;IACV,WAAW;IACX,OAAO;IACP,YAAY;IACZ,QAAQ;IACR,aAAa;IACb,iBAAiB;IACjB,KAAK;IACL,UAAU;CACX,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,MAAM,CAAC,OAAO,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAE9F,iCAAiC;AACjC,gCAAgC;AAChC,8BAA8B"}
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { RFCMetadata } from '../types/index.js';
|
|
6
6
|
/**
|
|
7
|
-
* RFCXML
|
|
7
|
+
* RFCXML を取得(並列フェッチ)
|
|
8
|
+
* 複数ソースに同時リクエストし、最初に成功したものを返す
|
|
8
9
|
*/
|
|
9
10
|
export declare function fetchRFCXML(rfcNumber: number): Promise<string>;
|
|
10
11
|
/**
|
|
@@ -12,7 +13,8 @@ export declare function fetchRFCXML(rfcNumber: number): Promise<string>;
|
|
|
12
13
|
*/
|
|
13
14
|
export declare function fetchRFCMetadata(rfcNumber: number): Promise<RFCMetadata>;
|
|
14
15
|
/**
|
|
15
|
-
* RFC
|
|
16
|
+
* RFC テキストを取得(並列フェッチ)
|
|
17
|
+
* 複数ソースに同時リクエストし、最初に成功したものを返す
|
|
16
18
|
*/
|
|
17
19
|
export declare function fetchRFCText(rfcNumber: number): Promise<string>;
|
|
18
20
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rfc-fetcher.d.ts","sourceRoot":"","sources":["../../src/services/rfc-fetcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"rfc-fetcher.d.ts","sourceRoot":"","sources":["../../src/services/rfc-fetcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAiBrD;;;GAGG;AACH,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA6BpE;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAoD9E;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA8BrE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,SAAgB,SAAS,EAAE,MAAM,CAAC;IAClC,SAAgB,QAAQ,EAAE,OAAO,CAAC;IAClC,SAAgB,UAAU,EAAE,MAAM,CAAC;gBAEvB,SAAS,EAAE,MAAM,EAAE,cAAc,GAAE,MAAM,EAAO;CAoB7D;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAIjC"}
|
|
@@ -2,32 +2,16 @@
|
|
|
2
2
|
* RFC 取得サービス
|
|
3
3
|
* RFCXML ソースの取得とキャッシュ管理
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
import { LRUCache } from '../utils/cache.js';
|
|
6
|
+
import { fetchFromMultipleSources } from '../utils/fetch.js';
|
|
7
|
+
import { CACHE_CONFIG, RFC_XML_SOURCES, RFC_TEXT_SOURCES, DATATRACKER_API, HTTP_CONFIG, RFC_CONFIG, } from '../config.js';
|
|
8
|
+
// LRU キャッシュ(設定は config.ts から)
|
|
9
|
+
const xmlCache = new LRUCache(CACHE_CONFIG.xml);
|
|
10
|
+
const textCache = new LRUCache(CACHE_CONFIG.text);
|
|
11
|
+
const metadataCache = new LRUCache(CACHE_CONFIG.metadata);
|
|
9
12
|
/**
|
|
10
|
-
*
|
|
11
|
-
|
|
12
|
-
const RFC_XML_SOURCES = {
|
|
13
|
-
// RFC Editor 公式
|
|
14
|
-
rfcEditor: (num) => `https://www.rfc-editor.org/rfc/rfc${num}.xml`,
|
|
15
|
-
// IETF Tools
|
|
16
|
-
ietfTools: (num) => `https://xml2rfc.ietf.org/public/rfc/rfc${num}.xml`,
|
|
17
|
-
// Datatracker
|
|
18
|
-
datatracker: (num) => `https://datatracker.ietf.org/doc/rfc${num}/xml/`,
|
|
19
|
-
};
|
|
20
|
-
/**
|
|
21
|
-
* RFC テキストソースの取得元
|
|
22
|
-
*/
|
|
23
|
-
const RFC_TEXT_SOURCES = {
|
|
24
|
-
// RFC Editor 公式(テキスト)
|
|
25
|
-
rfcEditor: (num) => `https://www.rfc-editor.org/rfc/rfc${num}.txt`,
|
|
26
|
-
// IETF Tools
|
|
27
|
-
ietfTools: (num) => `https://tools.ietf.org/rfc/rfc${num}.txt`,
|
|
28
|
-
};
|
|
29
|
-
/**
|
|
30
|
-
* RFCXML を取得
|
|
13
|
+
* RFCXML を取得(並列フェッチ)
|
|
14
|
+
* 複数ソースに同時リクエストし、最初に成功したものを返す
|
|
31
15
|
*/
|
|
32
16
|
export async function fetchRFCXML(rfcNumber) {
|
|
33
17
|
// キャッシュチェック
|
|
@@ -35,33 +19,27 @@ export async function fetchRFCXML(rfcNumber) {
|
|
|
35
19
|
if (cached) {
|
|
36
20
|
return cached;
|
|
37
21
|
}
|
|
38
|
-
//
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
catch (error) {
|
|
60
|
-
errors.push(error);
|
|
61
|
-
}
|
|
22
|
+
// ソースリストを作成
|
|
23
|
+
const sources = Object.entries(RFC_XML_SOURCES).map(([name, urlFn]) => ({
|
|
24
|
+
name,
|
|
25
|
+
url: urlFn(rfcNumber),
|
|
26
|
+
}));
|
|
27
|
+
try {
|
|
28
|
+
// 並列フェッチ(最初に成功したものを返す)
|
|
29
|
+
const { text: xml, source } = await fetchFromMultipleSources(sources, {
|
|
30
|
+
headers: { Accept: 'application/xml, text/xml' },
|
|
31
|
+
validate: (text) => text.includes('<?xml') || text.includes('<rfc'),
|
|
32
|
+
});
|
|
33
|
+
xmlCache.set(rfcNumber, xml);
|
|
34
|
+
console.error(`[RFC ${rfcNumber}] Fetched from ${source}`);
|
|
35
|
+
return xml;
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
// すべて失敗した場合
|
|
39
|
+
throw new RFCXMLNotAvailableError(rfcNumber, [
|
|
40
|
+
error instanceof Error ? error.message : String(error),
|
|
41
|
+
]);
|
|
62
42
|
}
|
|
63
|
-
// すべて失敗した場合
|
|
64
|
-
throw new RFCXMLNotAvailableError(rfcNumber, errors.map((e) => e.message));
|
|
65
43
|
}
|
|
66
44
|
/**
|
|
67
45
|
* RFC メタデータを取得(IETF Datatracker API)
|
|
@@ -72,12 +50,12 @@ export async function fetchRFCMetadata(rfcNumber) {
|
|
|
72
50
|
if (cached) {
|
|
73
51
|
return cached;
|
|
74
52
|
}
|
|
75
|
-
const url =
|
|
53
|
+
const url = DATATRACKER_API.document(rfcNumber);
|
|
76
54
|
try {
|
|
77
55
|
const response = await fetch(url, {
|
|
78
56
|
headers: {
|
|
79
57
|
Accept: 'application/json',
|
|
80
|
-
'User-Agent':
|
|
58
|
+
'User-Agent': HTTP_CONFIG.userAgent,
|
|
81
59
|
},
|
|
82
60
|
});
|
|
83
61
|
if (!response.ok) {
|
|
@@ -109,7 +87,8 @@ export async function fetchRFCMetadata(rfcNumber) {
|
|
|
109
87
|
}
|
|
110
88
|
}
|
|
111
89
|
/**
|
|
112
|
-
* RFC
|
|
90
|
+
* RFC テキストを取得(並列フェッチ)
|
|
91
|
+
* 複数ソースに同時リクエストし、最初に成功したものを返す
|
|
113
92
|
*/
|
|
114
93
|
export async function fetchRFCText(rfcNumber) {
|
|
115
94
|
// キャッシュチェック
|
|
@@ -117,43 +96,33 @@ export async function fetchRFCText(rfcNumber) {
|
|
|
117
96
|
if (cached) {
|
|
118
97
|
return cached;
|
|
119
98
|
}
|
|
120
|
-
//
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
catch (error) {
|
|
142
|
-
errors.push(error);
|
|
143
|
-
}
|
|
99
|
+
// ソースリストを作成
|
|
100
|
+
const sources = Object.entries(RFC_TEXT_SOURCES).map(([name, urlFn]) => ({
|
|
101
|
+
name,
|
|
102
|
+
url: urlFn(rfcNumber),
|
|
103
|
+
}));
|
|
104
|
+
try {
|
|
105
|
+
// 並列フェッチ(最初に成功したものを返す)
|
|
106
|
+
const { text, source } = await fetchFromMultipleSources(sources, {
|
|
107
|
+
headers: { Accept: 'text/plain' },
|
|
108
|
+
validate: (t) => t.includes('Request for Comments') || t.includes('RFC '),
|
|
109
|
+
});
|
|
110
|
+
textCache.set(rfcNumber, text);
|
|
111
|
+
console.error(`[RFC ${rfcNumber}] Text fetched from ${source}`);
|
|
112
|
+
return text;
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
// すべて失敗
|
|
116
|
+
throw new Error(`Failed to fetch RFC ${rfcNumber} text from all sources. ` +
|
|
117
|
+
`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
144
118
|
}
|
|
145
|
-
// すべて失敗
|
|
146
|
-
throw new Error(`Failed to fetch RFC ${rfcNumber} text from all sources. ` +
|
|
147
|
-
`Errors: ${errors.map((e) => e.message).join(', ')}`);
|
|
148
119
|
}
|
|
149
120
|
/**
|
|
150
121
|
* RFC が XML 形式で利用可能か確認
|
|
151
122
|
* 注: RFC 8650 (2019年12月) 以降は公式に RFCXML v3
|
|
152
123
|
*/
|
|
153
124
|
export function isRFCXMLAvailable(rfcNumber) {
|
|
154
|
-
|
|
155
|
-
// それ以前は一部のみ利用可能
|
|
156
|
-
return rfcNumber >= 8650;
|
|
125
|
+
return rfcNumber >= RFC_CONFIG.xmlAvailableFrom;
|
|
157
126
|
}
|
|
158
127
|
/**
|
|
159
128
|
* RFC XML 取得エラー
|
|
@@ -163,13 +132,14 @@ export class RFCXMLNotAvailableError extends Error {
|
|
|
163
132
|
isOldRFC;
|
|
164
133
|
suggestion;
|
|
165
134
|
constructor(rfcNumber, originalErrors = []) {
|
|
166
|
-
const
|
|
135
|
+
const threshold = RFC_CONFIG.xmlAvailableFrom;
|
|
136
|
+
const isOldRFC = rfcNumber < threshold;
|
|
167
137
|
const suggestion = isOldRFC
|
|
168
138
|
? `RFC ${rfcNumber} は RFCXML v3 より前の形式で公開されているため、XML が利用できない可能性があります。` +
|
|
169
139
|
`テキスト形式での取得を検討してください(ietf MCP の get_ietf_doc を使用)。`
|
|
170
140
|
: `RFC ${rfcNumber} の XML 取得に失敗しました。ネットワーク接続を確認してください。`;
|
|
171
141
|
super(`RFC ${rfcNumber} XML を取得できませんでした。\n` +
|
|
172
|
-
`理由: ${isOldRFC ?
|
|
142
|
+
`理由: ${isOldRFC ? `古い RFC (< ${threshold}) のため XML が利用できない可能性があります` : 'ネットワークエラー'}\n` +
|
|
173
143
|
`提案: ${suggestion}` +
|
|
174
144
|
(originalErrors.length > 0 ? `\n詳細: ${originalErrors.join(', ')}` : ''));
|
|
175
145
|
this.name = 'RFCXMLNotAvailableError';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rfc-fetcher.js","sourceRoot":"","sources":["../../src/services/rfc-fetcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"rfc-fetcher.js","sourceRoot":"","sources":["../../src/services/rfc-fetcher.ts"],"names":[],"mappings":"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"}
|