# 機能設計書 86-URL生成

## 概要

本ドキュメントは、「URL生成」機能の設計を定義する。URL生成機能は、Ghost内のすべてのリソース（記事、ページ、タグ、著者等）に対して一意のURLを生成・管理し、フロントエンドでのルーティングを支援するサービスである。

### 本機能の処理概要

UrlServiceは、Ghostのルーティング設定（routes.yaml）に基づいてリソースごとのURLを生成し、URLからリソースへの逆引きを可能にする中央集権的なURL管理システムを提供する。

**業務上の目的・背景**：Ghostでは記事、ページ、タグ、著者など多様なリソースが存在し、それぞれにSEOフレンドリーで一意のURLを割り当てる必要がある。パーマリンク構造のカスタマイズやコレクションベースのルーティングをサポートするため、統一されたURL管理サービスが必要である。

**機能の利用シーン**：
- 記事公開時のURL生成
- フロントエンドでのリクエストルーティング
- APIレスポンスでのリソースURL提供
- サイトマップ生成
- メタデータ（OGP、canonical URL）生成

**主要な処理内容**：
1. UrlGeneratorによるリソースURL生成
2. URLからリソースへの逆引き（getResource）
3. リソースIDからURLの取得（getUrlByResourceId）
4. ルーター登録とURL生成器の紐付け
5. URLキャッシュの管理

**関連システム・外部連携**：
- routes.yaml - カスタムルーティング設定
- フロントエンドルーター
- サイトマップサービス
- メタデータサービス

**権限による制御**：URL生成自体に権限制御はないが、リソースのアクセス制御は別途適用される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 全画面 | - | 補助機能 | URLの生成・解決 |

## 機能種別

URL管理サービス / ルーティング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| url | string | No | 検索するURL | 相対URL形式 |
| resourceId | string | No | リソースID | 24文字 |
| identifier | string | No | ルーター識別子 | - |
| filter | string | No | NQLフィルタ | - |
| resourceType | string | No | リソースタイプ | posts/pages/tags/authors |
| permalink | string | No | パーマリンク構造 | - |

### 入力データソース

- routes.yaml（ルーティング設定）
- データベース（posts, pages, tags, users等）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| url | string | 生成されたURL |
| resource | object | リソースオブジェクト |
| permalink | string | パーマリンク構造 |

### 出力先

- APIレスポンス
- フロントエンドルーター
- テンプレートコンテキスト

## 処理フロー

### 処理シーケンス

```
1. UrlService初期化
   └─ キャッシュハンドラの設定
   └─ Queue、Urls、Resourcesの初期化
2. ルーター登録（onRouterAddedType）
   └─ UrlGeneratorの作成
   └─ フィルタ、リソースタイプ、パーマリンクの設定
3. リソースフェッチとURL生成
   └─ DBからリソース取得
   └─ パーマリンク構造に基づくURL生成
4. URL解決（getResource/getUrlByResourceId）
   └─ キャッシュから検索
   └─ 該当リソースを返却
```

### フローチャート

```mermaid
flowchart TD
    A[UrlService初期化] --> B[キャッシュ読み込み]
    B --> C{キャッシュ存在?}
    C -->|Yes| D[キャッシュから復元]
    C -->|No| E[リソースフェッチ]
    E --> F[Queue開始]
    F --> G[UrlGenerator登録]
    G --> H[URL生成]
    H --> I[キャッシュ保存]

    J[getResource呼び出し] --> K[URLでキャッシュ検索]
    K --> L{見つかった?}
    L -->|Yes| M[リソース返却]
    L -->|No| N{初期化完了?}
    N -->|Yes| O[null返却]
    N -->|No| P[エラー: URLSERVICE_NOT_READY]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-86-01 | URL一意性 | 各URLは一意で衝突しない | 常時 |
| BR-86-02 | 登録順優先 | 複数リソースが同一URL生成可能な場合、先に登録されたルーターが優先 | URL衝突時 |
| BR-86-03 | 404フォールバック | URLが見つからない場合は/404/を返却 | getUrlByResourceId時 |
| BR-86-04 | 初期化待機 | 初期化未完了時はエラーを投げる | getResource時 |

### 計算ロジック

パーマリンク構造の変数展開:
- `/:slug/` → 記事のslugを展開
- `/:year/:month/:day/:slug/` → 日付とslugを展開
- `/:primary_tag/:slug/` → 主タグとslugを展開

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| リソースフェッチ | posts, tags, users | SELECT | URL生成対象リソースの取得 |

### テーブル別操作詳細

なし（URL情報はメモリキャッシュで管理）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| URLSERVICE_NOT_READY | InternalServerError | 初期化中にgetResourceが呼ばれた | 初期化完了を待機 |
| URLSERVICE_RESOURCE_NOT_FOUND | NotFoundError | 存在しないリソースID | エラー返却 |

### リトライ仕様

なし

## トランザクション仕様

なし（読み取り専用）

## パフォーマンス要件

- URL解決は高速なメモリキャッシュで実現
- 初期化時間はメトリクスで記録（url-service）

## セキュリティ考慮事項

- URLのサニタイズは呼び出し元で実施

## 備考

- labs.urlCacheフラグでキャッシュ永続化を制御

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: サービスのエントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.js | `ghost/core/core/server/services/url/index.js` | サービスエクスポート |
| 1-2 | url-service.js | `ghost/core/core/server/services/url/url-service.js` | メインサービスクラス |

**読解のコツ**: UrlServiceクラスが中央の管理クラス。constructor、init、getResource、getUrlByResourceIdが主要メソッド。

#### Step 2: URL生成ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | url-generator.js | `ghost/core/core/server/services/url/url-generator.js` | URL生成器 |
| 2-2 | urls.js | `ghost/core/core/server/services/url/urls.js` | URLキャッシュ管理 |
| 2-3 | resources.js | `ghost/core/core/server/services/url/resources.js` | リソース管理 |

**主要処理フロー**（url-service.js）:
- **19-46行目**: コンストラクタ、Queue/Urls/Resourcesの初期化
- **98-112行目**: onRouterAddedType - UrlGenerator登録
- **148-187行目**: getResource - URLからリソース取得
- **231-255行目**: getUrlByResourceId - リソースIDからURL取得
- **303-328行目**: init - サービス初期化

#### Step 3: キュー処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | queue.js | `ghost/core/core/server/services/url/queue.js` | イベントキュー |

### プログラム呼び出し階層図

```
UrlService
    │
    ├─ Queue (イベントキュー)
    │      ├─ started イベント
    │      └─ ended イベント
    │
    ├─ Urls (URLキャッシュ)
    │      ├─ getByUrl()
    │      ├─ getByResourceId()
    │      └─ reset()
    │
    ├─ Resources (リソース管理)
    │      ├─ fetchResources()
    │      ├─ getAll()
    │      └─ releaseAll()
    │
    └─ UrlGenerator[] (URL生成器配列)
           ├─ identifier
           ├─ filter
           ├─ resourceType
           ├─ permalink
           └─ hasId()
```

### データフロー図

```
[入力]               [処理]                    [出力]

routes.yaml     ───▶ UrlGenerator           ───▶ URL pattern
  (config)           registration

DB Resources    ───▶ Resources.fetch        ───▶ URL cache
  (posts, etc)       & URL generation            (Urls)

URL Request     ───▶ getResource()          ───▶ Resource object
  (/path/)           (cache lookup)

Resource ID     ───▶ getUrlByResourceId()   ───▶ URL string
  (24char)           (cache lookup)              or /404/
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.js | `ghost/core/core/server/services/url/index.js` | ソース | サービスエクスポート |
| url-service.js | `ghost/core/core/server/services/url/url-service.js` | ソース | メインサービス |
| url-generator.js | `ghost/core/core/server/services/url/url-generator.js` | ソース | URL生成器 |
| urls.js | `ghost/core/core/server/services/url/urls.js` | ソース | URLキャッシュ |
| resources.js | `ghost/core/core/server/services/url/resources.js` | ソース | リソース管理 |
| queue.js | `ghost/core/core/server/services/url/queue.js` | ソース | イベントキュー |
| config.js | `ghost/core/core/server/services/url/config.js` | ソース | 設定 |
| resource.js | `ghost/core/core/server/services/url/resource.js` | ソース | リソースクラス |
| local-file-cache.js | `ghost/core/core/server/services/url/local-file-cache.js` | ソース | ファイルキャッシュ |
