petari 0.4.0 → 0.4.1
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.md +7 -0
- package/dist/commands/show.js +35 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -72,6 +72,10 @@ petari の更新で規約文が変わった場合は、`petari init` を再実
|
|
|
72
72
|
- **エンコーディング保全**: Shift_JIS / UTF-8 (BOM 有無)・CRLF / LF・末尾改行を完全維持。
|
|
73
73
|
変更していない行は元のバイト列をそのまま書き戻す (レガシー VB.NET 資産でも安全)
|
|
74
74
|
- **失敗レポート**: そのまま AI チャットに貼り返せる形式で出力。再依頼が 1 コピペで済む
|
|
75
|
+
- **git / VS Code がない端末でも差分確認・手修正**: `show` は VS Code がなければ自己完結
|
|
76
|
+
HTML レポートをブラウザで開き、`show --edit` は同梱の Monaco Editor (VS Code と同じ
|
|
77
|
+
差分エディタ) で現在のファイルを差分を見ながら直接編集・保存できる
|
|
78
|
+
(もちろんエンコーディング保全つき)
|
|
75
79
|
- **実行時依存ゼロ**: サプライチェーン対策として npm の実行時依存パッケージを持たない
|
|
76
80
|
(Shift_JIS 変換テーブルも Node 組み込み ICU から自動生成して同梱)。
|
|
77
81
|
唯一の同梱サードパーティはブラウザ編集 UI の Monaco Editor (Microsoft 製・MIT) で、
|
|
@@ -140,6 +144,9 @@ changes.md (AI 出力)・クリップボード・リポジトリに同梱され
|
|
|
140
144
|
- 検証と書き込みの間の TOCTOU (ファイル差し替え) は検出しません (単独利用の CLI として許容)
|
|
141
145
|
- 履歴には対象ファイルの複製が平文で保存されます。`.petari/` は `.gitignore` 推奨
|
|
142
146
|
(init が自動提案) で、リポジトリには含まれません
|
|
147
|
+
- ブラウザ表示用の差分レポート (HTML) はコードの中身を平文で含み、本人のみ読める
|
|
148
|
+
一時ディレクトリ (0700) に書き出されます。1 時間より古いものは次回の `show` 実行時に
|
|
149
|
+
自動削除されます (閲覧中かもしれない直近分は残す)
|
|
143
150
|
|
|
144
151
|
## 開発
|
|
145
152
|
|
package/dist/commands/show.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* ブラウザ経路では全ファイルをまとめて表示する。
|
|
13
13
|
*/
|
|
14
14
|
import { execFile } from "node:child_process";
|
|
15
|
-
import { existsSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
|
|
15
|
+
import { existsSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
16
16
|
import { tmpdir } from "node:os";
|
|
17
17
|
import { isAbsolute, join } from "node:path";
|
|
18
18
|
import { parseArgs } from "node:util";
|
|
@@ -154,10 +154,43 @@ export function generateReportHtml(root, hdir, id, entries, mine) {
|
|
|
154
154
|
const title = `petari 履歴 ${id}${mine ? " (手修正分)" : ""}`;
|
|
155
155
|
return buildReportPage(title, new Date().toLocaleString("ja-JP"), sections);
|
|
156
156
|
}
|
|
157
|
+
const REPORT_DIR_PREFIX = "petari-report-";
|
|
158
|
+
const REPORT_TTL_MS = 60 * 60_000;
|
|
159
|
+
/**
|
|
160
|
+
* 過去の一時レポートを掃除する (§4.3)。レポートはコードの中身を平文で含むため
|
|
161
|
+
* 残し続けない。ブラウザで閲覧中かもしれない直近 1 時間分は残し、次回実行時に消す。
|
|
162
|
+
* 対象は tmpdir 直下の petari-report-* ディレクトリのみ (symlink は Dirent 判定で除外)。
|
|
163
|
+
*/
|
|
164
|
+
export function cleanupOldReports(now = Date.now()) {
|
|
165
|
+
let removed = 0;
|
|
166
|
+
let entries;
|
|
167
|
+
try {
|
|
168
|
+
entries = readdirSync(tmpdir(), { withFileTypes: true });
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return 0;
|
|
172
|
+
}
|
|
173
|
+
for (const ent of entries) {
|
|
174
|
+
if (!ent.isDirectory() || !ent.name.startsWith(REPORT_DIR_PREFIX))
|
|
175
|
+
continue;
|
|
176
|
+
const dir = join(tmpdir(), ent.name);
|
|
177
|
+
try {
|
|
178
|
+
if (now - statSync(dir).mtimeMs < REPORT_TTL_MS)
|
|
179
|
+
continue;
|
|
180
|
+
rmSync(dir, { recursive: true, force: true });
|
|
181
|
+
removed++;
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
// 使用中・権限エラー等は無視 (次回実行時に再試行される)
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return removed;
|
|
188
|
+
}
|
|
157
189
|
/** 静的レポートを一時ファイルへ書き出してブラウザで開く */
|
|
158
190
|
async function runBrowserReport(root, hdir, id, entries, mine, noOpen) {
|
|
191
|
+
cleanupOldReports();
|
|
159
192
|
const html = generateReportHtml(root, hdir, id, entries, mine);
|
|
160
|
-
const reportPath = join(mkdtempSync(join(tmpdir(),
|
|
193
|
+
const reportPath = join(mkdtempSync(join(tmpdir(), REPORT_DIR_PREFIX)), "report.html");
|
|
161
194
|
writeFileSync(reportPath, html);
|
|
162
195
|
out(`差分レポートを書き出しました: ${reportPath}`);
|
|
163
196
|
if (!noOpen) {
|