# Orankitの変換処理をローカルで使う Node.js 22以降だけで動く公開CLIです。CSV→JSON、JSON整形・圧縮、TOML→JSON、JSON→TOMLを、既存のツールと同じ処理で実行できます。公開CLIの実行にpnpm、tsx、依存関係のインストールは不要です。 実行中にネットワークへ接続したり、アクセス解析へ送信したりする処理はありません。入力はファイルまたは標準入力から読み取り、結果は標準出力または指定ファイルに出します。入力内容からURLを作る処理もありません。 ## 公開CLIを取得して固定する Node.js 22以降とcurlを用意し、新しいディレクトリにCLI、manifest、依存ライセンスをダウンロードします。この説明は [README.txt](https://orankit.com/cli/README.txt) でも公開しています。 ```sh mkdir orankit-cli cd orankit-cli curl --fail --location --output orankit.mjs https://orankit.com/cli/orankit.mjs curl --fail --location --output manifest.json https://orankit.com/cli/manifest.json curl --fail --location --output THIRD_PARTY_NOTICES.txt https://orankit.com/cli/THIRD_PARTY_NOTICES.txt ``` 3つの取得が成功したことを確認し、CLIを実行する前に、Node.js標準のcryptoでファイル全体のSHA-256をmanifestと照合します。照合したハッシュは`PINNED_SHA256`に保存します。 ```sh node --input-type=module <<'NODE' import { createHash } from 'node:crypto'; import { readFileSync, writeFileSync } from 'node:fs'; if (Number(process.versions.node.split('.')[0]) < 22) { throw new Error('Node.js >=22 is required.'); } const manifest = JSON.parse(readFileSync('manifest.json', 'utf8')); if (manifest.artifact !== 'orankit.mjs' || !/^[a-f0-9]{64}$/.test(manifest.sha256)) { throw new Error('Invalid CLI manifest.'); } const actual = createHash('sha256').update(readFileSync('orankit.mjs')).digest('hex'); if (actual !== manifest.sha256) throw new Error('CLI SHA-256 mismatch.'); writeFileSync('PINNED_SHA256', actual + '\n', { flag: 'wx' }); console.log('Verified SHA-256: ' + actual); NODE ``` 照合が成功してから、ヘルプと少量の代表データで動作を確認します。ダウンロードや照合が失敗した場合は実行せず、新しいディレクトリへ取り直してください。公開の更新と取得のタイミングが重なる場合も、照合で不一致を検出できます。 ```sh node ./orankit.mjs --help ``` `manifest.json`には`artifact`、ファイル全体の`sha256`、`runtime: "Node.js >=22"`、対応する5つの`commands`、`documentation: "README.txt"`が入っています。ハッシュは取得したファイルの一致確認とバージョン固定に使います。自動化では、確認済みの`orankit.mjs`、`manifest.json`、`PINNED_SHA256`、`THIRD_PARTY_NOTICES.txt`をローカルで保持し、選んだハッシュを設定にも残してください。更新は新しいディレクトリで再取得・照合してから意図的に切り替えます。 公開URLは更新されます。以前のバージョンを同じURLから取得できる保証はありません。初回のダウンロードにはネットワークが必要ですが、保存したCLIでの変換にはネットワークは不要です。依存するsmol-tomlのライセンスは`THIRD_PARTY_NOTICES.txt`に同梱しています。 ## 実行例 標準入力からJSONを整形します。大きな整数の数字も保持します。 ```sh printf '%s\n' '{"id":9007199254740993}' | node ./orankit.mjs json-formatter --indent 4 ``` CSVファイルを読み取り、結果を新しいファイルに保存します。ヘッダーがあるCSVでは、列名をキーとするオブジェクトの配列になります。 ```sh node ./orankit.mjs csv-to-json --input ./data.csv --output ./converted.json ``` タブ区切り・ヘッダーなしの入力は、行ごとの配列に変換できます。 ```sh node ./orankit.mjs csv-to-json --input ./data.tsv --delimiter tab --no-header ``` 変換結果をパイプでつなぐこともできます。 ```sh set -o pipefail node ./orankit.mjs csv-to-json --input ./data.csv | node ./orankit.mjs json-minifier --output ./converted.min.json ``` TOMLとJSONの変換方向は、コマンド名で指定します。 ```sh node ./orankit.mjs toml-to-json --input ./config.toml --output ./config.json node ./orankit.mjs json-to-toml --input ./source.json --output ./converted.toml ``` `--input`の省略または`--input -`は標準入力、`--output`の省略または`--output -`は標準出力です。出力が改行で終わらない場合は、末尾改行を付けます。上の例はCLIを保存したディレクトリで実行します。別の作業ディレクトリからはCLIへのパスを指定してください。入力・出力には相対パスも絶対パスも使えます。 ## ファイルの扱いと失敗の判定 - ファイルはUTF-8で読みます。不正なUTF-8を代替文字に置き換えず、エラーにします。 - 結果ファイルの親ディレクトリは、事前に用意してください。 - 既存の出力には、明示的な`--force`なしでは上書きしません。 - 入力と出力が同じファイルの場合は、`--force`でも拒否します。ハードリンクなどの別名と、標準入力へリダイレクトした通常ファイルも確認します。出力先のシンボリックリンクは拒否します。 - この保護は`--output`で指定した保存先が対象です。入力と同じファイルへのシェルの`>`リダイレクトは、CLI起動前にシェルがファイルを空にするため防げません。ファイル保存には`--output`を使ってください。 - 変換が失敗した場合、新しい出力ファイルは作りません。`--force`を指定しても、既存の出力は変換が成功するまで変更しません。 - ファイル出力は同じ親ディレクトリ内で一時ファイルに書き、完成後に配置します。新規出力の権限は`0600`です。保存先のファイルシステムでは通常のファイルとハードリンクを使える必要があります。 - 処理は入力全体をメモリに読み込みます。ストリーミング変換ではありません。 終了コードは次の通りです。 | コード | 意味 | | ------ | ---------------------------------------------------------- | | `0` | 成功。結果は標準出力または指定ファイルにあります | | `1` | 入力の読取、変換、保存等の失敗 | | `2` | 未対応コマンド、オプション不足、形式に合わないオプション等 | エラーは標準エラー出力へ短い説明を出します。入力本文、出力本文、パスやファイル名はエラーに含めません。JSONの構文エラーなど、入力の一部を含む可能性がある内部エラーもそのまま表示しません。 既存出力を置き換える場合だけ、次のように指定してください。 ```sh node ./orankit.mjs json-minifier --input ./source.json --output ./result.json --force ``` ## 対応範囲 CSVでは引用符内の改行や空白を保持します。重複・空のヘッダー、列数の不一致、不正な引用符はエラーになります。`--delimiter`は`comma`、`tab`、`semicolon`、`pipe`です。 JSON整形・圧縮は数字、文字列のエスケープ、キー順、重複キーを保持して空白を調整します。`--indent 2|4`はJSON整形だけに指定できます。 TOML変換は既存ツールと同じ制限があります。JSON→TOMLではnull、重複キー、精度を失う数値等を拒否します。ネストは最大100段です。TOMLの数値はJavaScriptの浮動小数点表現、日時はミリ秒精度になります。数字や日時の細かい精度をそのまま保持したい値は、文字列として扱ってください。 ## リポジトリから実行する場合 リポジトリへのアクセス権がある場合は、ソースから実行することもできます。公開CLIの利用にはこの手順は必要ありません。Node.js 22以降と、リポジトリに固定されたpnpmを使います。初回のcloneと依存関係の取得にはネットワークが必要です。 ```sh ORANKIT_REPOSITORY='アクセス権のあるリポジトリURLに置き換える' git clone "$ORANKIT_REPOSITORY" orankit cd orankit ORANKIT_COMMIT='CLIを含むレビュー済みの完全なコミットSHAに置き換える' git checkout --detach "$ORANKIT_COMMIT" pnpm install --frozen-lockfile pnpm --silent tool:run --help ``` 使用するコミットSHAを自動化の設定に残します。依存関係を導入した後は、変換の実行にネットワークは不要です。リポジトリのディレクトリで、公開CLIの`node ./orankit.mjs`の代わりに`pnpm --silent tool:run`を使えます。`--silent`はpnpmの実行バナーを標準出力に混ぜないための指定です。 公開ファイルを自分でビルドする場合は、`pnpm build:cli`を実行します。`static/cli/`にCLI、manifest、依存ライセンス、公開説明が生成されます。検証用の別ディレクトリへ出す場合は、`pnpm build:cli --outdir <出力ディレクトリ>`を指定します。 このCLIの目的は、実際のファイル変換やエージェントの作業へ組み込んで、同じ処理を繰り返し使えるかを確かめることです。まずローカルに固定したCLIと少量の代表データで動作を確認し、手作業のどの工程を置き換えたかを記録すると、次の改善を選びやすくなります。