# API設計書

## 概要

本ドキュメントは、CoffeeScriptコンパイラが提供するNode.js API（プログラミングインターフェース）を定義します。CoffeeScriptはWebアプリケーションフレームワークではなく、JavaScriptへのトランスパイラであるため、HTTP APIではなく、Node.jsモジュールとして利用可能なプログラミングAPIを提供します。

**注意**: 本プロジェクトはHTTPベースのREST APIを提供していません。以下はNode.jsモジュールとしてのAPI仕様です。

## 共通仕様

### モジュールインポート

```javascript
// CommonJS
const CoffeeScript = require('coffeescript');

// ES Modules
import { compile, tokens, nodes } from 'coffeescript';
```

### バージョン情報

| 項目 | 値 |
| --- | --- |
| 現在のバージョン | 2.7.0 |
| 対応Node.jsバージョン | >= 6 |
| サポートするファイル拡張子 | `.coffee`, `.litcoffee`, `.coffee.md` |

### 共通エラー

| エラー種別 | 説明 |
| --- | --- |
| SyntaxError | CoffeeScriptの構文エラー（ソースコードの位置情報を含む） |
| Error | Babelトランスパイルオプション使用時のBabelモジュール未インストールエラー |

## API一覧

| カテゴリ | メソッド | 説明 |
| --- | --- | --- |
| コンパイル | compile | CoffeeScriptコードをJavaScriptにコンパイル |
| コンパイル | transpile | Babelを使用してJavaScriptをトランスパイル |
| 実行 | run | CoffeeScriptコードをコンパイルして実行 |
| 実行 | eval | CoffeeScriptコードを評価（サンドボックス対応） |
| 解析 | tokens | CoffeeScriptコードをトークン化 |
| 解析 | nodes | CoffeeScriptコードをAST（抽象構文木）に変換 |
| 登録 | register | require.extensionsにCoffeeScriptハンドラを登録 |
| ユーティリティ | patchStackTrace | スタックトレースをCoffeeScriptソース位置にマッピング |
| 内部 | _compileFile | ファイルからCoffeeScriptをコンパイル（内部API） |
| 内部 | _compileRawFileContent | 生のファイル内容からCoffeeScriptをコンパイル（内部API） |
| 定数 | VERSION | CoffeeScriptのバージョン文字列 |
| 定数 | FILE_EXTENSIONS | サポートするファイル拡張子の配列 |
| オブジェクト | helpers | ヘルパー関数群 |

## 各APIエンドポイント定義

### コンパイル

#### 1. compile

CoffeeScriptコードをJavaScriptにコンパイルします。

**基本情報**

| 項目 | 内容 |
| --- | --- |
| シグネチャ | `CoffeeScript.compile(code, options)` |
| 戻り値 | `string` または `{js, sourceMap, v3SourceMap}` |

**パラメータ**

| パラメータ名 | 型 | 必須 | デフォルト | 説明 |
| --- | --- | --- | --- | --- |
| code | string | ○ | - | コンパイルするCoffeeScriptソースコード |
| options | object | - | {} | コンパイルオプション |

**オプション（options）**

| フィールド名 | 型 | 必須 | デフォルト | 説明 |
| --- | --- | --- | --- | --- |
| bare | boolean | - | false | trueの場合、IIFE（即時実行関数式）でラップしない |
| header | boolean | - | false | trueの場合、生成コード先頭にバージョンコメントを追加 |
| sourceMap | boolean | - | false | trueの場合、ソースマップを含むオブジェクトを返す |
| inlineMap | boolean | - | false | trueの場合、インラインソースマップをJSに埋め込む |
| filename | string | - | - | ソースファイル名（エラーメッセージ・ソースマップ用） |
| literate | boolean | - | false | trueの場合、Literate CoffeeScriptとして解析 |
| ast | boolean | - | false | trueの場合、JSの代わりにASTを返す |
| transpile | object | - | - | Babelトランスパイルオプション |
| shiftLine | boolean | - | false | 行番号をシフト |
| sourceRoot | string | - | - | ソースマップのsourceRoot |
| sourceFiles | array | - | - | ソースマップのsourcesフィールド |

**使用例（成功時）**

```javascript
const CoffeeScript = require('coffeescript');

// 基本的なコンパイル
const js = CoffeeScript.compile('square = (x) -> x * x');
console.log(js);
// 出力:
// (function() {
//   var square;
//   square = function(x) {
//     return x * x;
//   };
// }).call(this);

// bareモードでコンパイル
const bareJs = CoffeeScript.compile('square = (x) -> x * x', { bare: true });
console.log(bareJs);
// 出力:
// var square;
// square = function(x) {
//   return x * x;
// };

// ソースマップ付きでコンパイル
const result = CoffeeScript.compile('square = (x) -> x * x', {
  sourceMap: true,
  filename: 'example.coffee'
});
console.log(result.js);          // コンパイルされたJavaScript
console.log(result.v3SourceMap); // V3形式のソースマップJSON文字列
console.log(result.sourceMap);   // SourceMapオブジェクト

// ASTを取得
const ast = CoffeeScript.compile('x = 1', { ast: true });
console.log(ast); // ESTree互換のAST
```

**使用例（エラー時）**

```javascript
try {
  CoffeeScript.compile('invalid -> ->');
} catch (error) {
  console.log(error.message);
  // "unexpected ->"
  console.log(error.location);
  // { first_line: 0, first_column: 11, ... }
}
```

---

#### 2. transpile

Babelを使用してJavaScriptをトランスパイルします。

**基本情報**

| 項目 | 内容 |
| --- | --- |
| シグネチャ | `CoffeeScript.transpile(js, options)` |
| 戻り値 | Babelの変換結果オブジェクト |
| 前提条件 | `@babel/core`または`babel-core`モジュールがインストールされていること |

**パラメータ**

| パラメータ名 | 型 | 必須 | 説明 |
| --- | --- | --- | --- |
| js | string | ○ | トランスパイルするJavaScriptコード |
| options | object | - | Babelに渡すオプション |

**使用例**

```javascript
const CoffeeScript = require('coffeescript');

const js = 'const fn = () => 42;';
const result = CoffeeScript.transpile(js, {
  presets: ['@babel/preset-env']
});
console.log(result.code);
```

**エラー時**

```javascript
// Babelがインストールされていない場合
// Error: To use the transpile option, you must have the '@babel/core' module installed
```

---

### 実行

#### 3. run

CoffeeScriptコードをコンパイルして即座に実行します（Node.js環境専用）。

**基本情報**

| 項目 | 内容 |
| --- | --- |
| シグネチャ | `CoffeeScript.run(code, options)` |
| 戻り値 | 実行結果 |
| 環境 | Node.js専用 |

**パラメータ**

| パラメータ名 | 型 | 必須 | デフォルト | 説明 |
| --- | --- | --- | --- | --- |
| code | string | ○ | - | 実行するCoffeeScriptコード |
| options | object | - | {} | オプション |

**オプション（options）**

| フィールド名 | 型 | 必須 | デフォルト | 説明 |
| --- | --- | --- | --- | --- |
| filename | string | - | - | ソースファイル名（`__filename`に設定される） |

**使用例**

```javascript
const CoffeeScript = require('coffeescript');

CoffeeScript.run(`
  greeting = "Hello, World!"
  console.log greeting
`);
// 出力: Hello, World!
```

---

#### 4. eval

CoffeeScriptコードをサンドボックス環境で評価します。

**基本情報**

| 項目 | 内容 |
| --- | --- |
| シグネチャ | `CoffeeScript.eval(code, options)` |
| 戻り値 | 評価結果 |

**パラメータ**

| パラメータ名 | 型 | 必須 | デフォルト | 説明 |
| --- | --- | --- | --- | --- |
| code | string | ○ | - | 評価するCoffeeScriptコード |
| options | object | - | {} | オプション |

**オプション（options）**

| フィールド名 | 型 | 必須 | デフォルト | 説明 |
| --- | --- | --- | --- | --- |
| sandbox | object | - | global | 実行コンテキスト（サンドボックス） |
| filename | string | - | 'eval' | `__filename`に設定される値 |
| modulename | string | - | 'eval' | モジュール名 |

**使用例**

```javascript
const CoffeeScript = require('coffeescript');

// 基本的な評価
const result = CoffeeScript.eval('x = 1 + 2');
console.log(result); // 3

// サンドボックス環境での評価
const sandbox = { value: 10 };
CoffeeScript.eval('result = value * 2', { sandbox });
console.log(sandbox.result); // 20
```

---

### 解析

#### 5. tokens

CoffeeScriptコードをトークン化します。

**基本情報**

| 項目 | 内容 |
| --- | --- |
| シグネチャ | `CoffeeScript.tokens(code, options)` |
| 戻り値 | トークン配列 |

**パラメータ**

| パラメータ名 | 型 | 必須 | 説明 |
| --- | --- | --- | --- |
| code | string | ○ | トークン化するCoffeeScriptコード |
| options | object | - | オプション |

**使用例**

```javascript
const CoffeeScript = require('coffeescript');

const tokenList = CoffeeScript.tokens('x = 1');
console.log(tokenList);
// [
//   ['IDENTIFIER', 'x', { ... }],
//   ['=', '=', { ... }],
//   ['NUMBER', '1', { ... }],
//   ['TERMINATOR', '\n', { ... }]
// ]
```

**トークン形式**

各トークンは `[tag, value, locationData]` 形式の配列です。

| インデックス | 説明 |
| --- | --- |
| 0 | トークンタグ（'IDENTIFIER', 'NUMBER', '='など） |
| 1 | トークンの値 |
| 2 | 位置情報（first_line, first_column, last_line, last_column, range） |

---

#### 6. nodes

CoffeeScriptコードをAST（抽象構文木）に変換します。

**基本情報**

| 項目 | 内容 |
| --- | --- |
| シグネチャ | `CoffeeScript.nodes(source, options)` |
| 戻り値 | ASTノード |

**パラメータ**

| パラメータ名 | 型 | 必須 | 説明 |
| --- | --- | --- | --- |
| source | string または array | ○ | CoffeeScriptコードまたはトークン配列 |
| options | object | - | オプション |

**使用例**

```javascript
const CoffeeScript = require('coffeescript');

// ソースコードからAST
const ast = CoffeeScript.nodes('x = 1 + 2');
console.log(ast);

// ASTをコンパイル
const js = ast.compile({ bare: true });
console.log(js);

// ASTをトラバース
ast.traverseChildren(true, (node) => {
  console.log(node.constructor.name);
});
```

---

### 登録

#### 7. register

Node.jsのrequire.extensionsにCoffeeScriptファイルハンドラを登録します。

**基本情報**

| 項目 | 内容 |
| --- | --- |
| シグネチャ | `CoffeeScript.register()` |
| 戻り値 | register モジュール |
| 代替方法 | `require('coffeescript/register')` |

**使用例**

```javascript
// 方法1: register関数を使用
const CoffeeScript = require('coffeescript');
CoffeeScript.register();
require('./myfile.coffee');

// 方法2: registerモジュールを直接require
require('coffeescript/register');
require('./myfile.coffee');
```

---

### ユーティリティ

#### 8. patchStackTrace

スタックトレースをCoffeeScriptのソース位置にマッピングします。

**基本情報**

| 項目 | 内容 |
| --- | --- |
| シグネチャ | `CoffeeScript.patchStackTrace()` |
| 戻り値 | なし |
| 効果 | Error.prepareStackTraceをオーバーライド |

**使用例**

```javascript
const CoffeeScript = require('coffeescript');
CoffeeScript.patchStackTrace();

// これ以降、スタックトレースはCoffeeScriptのソース位置を表示
```

---

### 内部API

#### 9. _compileFile

ファイルシステムからCoffeeScriptファイルを読み込んでコンパイルします。

**基本情報**

| 項目 | 内容 |
| --- | --- |
| シグネチャ | `CoffeeScript._compileFile(filename, options)` |
| 戻り値 | コンパイル結果 |
| 注意 | 内部API（アンダースコアプレフィックス） |

**パラメータ**

| パラメータ名 | 型 | 必須 | 説明 |
| --- | --- | --- | --- |
| filename | string | ○ | コンパイルするファイルのパス |
| options | object | - | コンパイルオプション |

---

#### 10. _compileRawFileContent

生のファイル内容（文字列）からCoffeeScriptをコンパイルします。

**基本情報**

| 項目 | 内容 |
| --- | --- |
| シグネチャ | `CoffeeScript._compileRawFileContent(raw, filename, options)` |
| 戻り値 | コンパイル結果 |
| 注意 | 内部API（アンダースコアプレフィックス） |

**パラメータ**

| パラメータ名 | 型 | 必須 | 説明 |
| --- | --- | --- | --- |
| raw | string | ○ | ファイルの生の内容 |
| filename | string | ○ | ファイル名（エラーメッセージ・literate判定用） |
| options | object | - | コンパイルオプション |

---

### 定数・プロパティ

#### 11. VERSION

CoffeeScriptのバージョン文字列。

**基本情報**

| 項目 | 内容 |
| --- | --- |
| 型 | string |
| 現在の値 | "2.7.0" |

```javascript
const CoffeeScript = require('coffeescript');
console.log(CoffeeScript.VERSION); // "2.7.0"
```

---

#### 12. FILE_EXTENSIONS

CoffeeScriptがサポートするファイル拡張子の配列。

**基本情報**

| 項目 | 内容 |
| --- | --- |
| 型 | string[] |
| 値 | ['.coffee', '.litcoffee', '.coffee.md'] |

```javascript
const CoffeeScript = require('coffeescript');
console.log(CoffeeScript.FILE_EXTENSIONS);
// ['.coffee', '.litcoffee', '.coffee.md']
```

---

#### 13. helpers

ヘルパー関数群を含むオブジェクト。

**主なヘルパー関数**

| 関数名 | 説明 |
| --- | --- |
| isLiterate(filename) | ファイル名がLiterate CoffeeScriptかどうか判定 |
| isCoffee(filename) | ファイル名がCoffeeScriptファイルかどうか判定 |
| invertLiterate(code) | Literate CoffeeScriptからコードを抽出 |
| throwSyntaxError(message, location) | 位置情報付きSyntaxErrorをスロー |

```javascript
const CoffeeScript = require('coffeescript');

console.log(CoffeeScript.helpers.isLiterate('test.litcoffee')); // true
console.log(CoffeeScript.helpers.isCoffee('test.coffee'));       // true
```

---

## ブラウザAPI

ブラウザ環境では、以下の追加APIが利用可能です。

### load

XHRを使用してリモートのCoffeeScriptファイルを読み込んで実行します。

**基本情報**

| 項目 | 内容 |
| --- | --- |
| シグネチャ | `CoffeeScript.load(url, callback, options, hold)` |
| 環境 | ブラウザ専用 |

**パラメータ**

| パラメータ名 | 型 | 必須 | デフォルト | 説明 |
| --- | --- | --- | --- | --- |
| url | string | ○ | - | CoffeeScriptファイルのURL |
| callback | function | - | - | 読み込み完了時のコールバック |
| options | object | - | {} | コンパイルオプション |
| hold | boolean | - | false | trueの場合、自動実行しない |

---

### runScripts

ページ内の`text/coffeescript`スクリプトタグを検出してコンパイル・実行します。

**基本情報**

| 項目 | 内容 |
| --- | --- |
| シグネチャ | `CoffeeScript.runScripts()` |
| 環境 | ブラウザ専用 |
| 自動実行 | DOMContentLoaded時に自動的に呼び出される |

**対応するスクリプトタイプ**

- `text/coffeescript`
- `text/literate-coffeescript`

---

## 備考

### ESモジュールとしてのインポート

CoffeeScript 2.x以降では、ES Modulesスタイルでのインポートもサポートされています。

```javascript
import CoffeeScript from 'coffeescript';
import { compile, tokens, nodes } from 'coffeescript';
```

### Babelとの連携

`transpile`オプションを使用する場合は、事前に`@babel/core`とプリセットをインストールする必要があります。

```bash
npm install @babel/core @babel/preset-env
```

```javascript
const CoffeeScript = require('coffeescript');

const js = CoffeeScript.compile('fn = => @value', {
  transpile: {
    presets: ['@babel/preset-env']
  }
});
```

### child_process.forkの拡張

`coffeescript/register`をrequireすると、`child_process.fork`がパッチされ、CoffeeScriptファイルを直接フォークできるようになります。

```javascript
require('coffeescript/register');
const { fork } = require('child_process');

// CoffeeScriptファイルを直接フォーク可能
fork('./worker.coffee');
```
