browser-git-ops 0.0.0 → 0.0.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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 nojaja
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 nojaja
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,146 +1,146 @@
1
- # browser-git-ops
2
-
3
- **目的**: ブラウザネイティブ環境(OPFS + Github/Gitlab APIs)で動作する軽量な Git 操作ライブラリを提供します。VirtualFS によるローカル差分生成と、GitHub/GitLab 向けのアダプタを通じたリモート操作を抽象化します。
4
-
5
- **主な特徴**
6
- - **仮想ファイルシステム (VirtualFS)**: ローカルワークスペースとベーススナップショットを管理し、変更セット(create/update/delete)を生成します。
7
- - **Git アダプタ抽象**: `GitAdapter` インターフェースに準拠するアダプタで GitHub/GitLab API を操作できます(サンプル実装あり)。
8
- - **Idempotent push**: commitKey による冪等処理サポート。
9
- - **衝突検知とマージ補助**: リモート差分取り込み時にローカルの未コミット変更を検出して conflicts を報告します。
10
-
11
- **注意(⚠️)**: 実装はユーティリティ/ライブラリ向けで、環境やアクセストークンの管理、エラーハンドリング方針は利用側で制御してください。
12
-
13
- **プロジェクト構成(抜粋)**
14
- - **src/virtualfs/virtualfs.ts**: VirtualFS 本体(初期化、read/write、push/pull、差分生成) - [src/virtualfs/virtualfs.ts](src/virtualfs/virtualfs.ts)
15
- - **src/virtualfs/persistence.ts**: ストレージバックエンドの抽象と Node 用実装 - [src/virtualfs/persistence.ts](src/virtualfs/persistence.ts)
16
- - **src/git/adapter.ts**: `GitAdapter` インターフェース定義 - [src/git/adapter.ts](src/git/adapter.ts)
17
- - **src/git/githubAdapter.ts**: GitHub 用アダプタ(blob/tree/commit フロー、再試行ロジック) - [src/git/githubAdapter.ts](src/git/githubAdapter.ts)
18
- - **test/**: ユニット/E2E テスト群(Jest / Playwright) - [test](test)
19
-
20
- **技術スタック**
21
- - TypeScript 5.x
22
- - Node.js (ESM, `type: "module"`)
23
- - テスト: Jest(unit) / Playwright(E2E)
24
- - ビルド: `tsc`
25
-
26
- --------------------------------------------------
27
- **クイックスタート(開発用)**
28
-
29
- 1. 依存インストール
30
-
31
- ```bash
32
- npm ci
33
- ```
34
-
35
- 2. ユニットテスト実行
36
-
37
- ```bash
38
- npm run test
39
- ```
40
-
41
- 3. E2E テスト(Playwright)
42
-
43
- ```bash
44
- npm run test:e2e
45
- ```
46
-
47
- 4. ビルド
48
-
49
- ```bash
50
- npm run build
51
- ```
52
-
53
- --------------------------------------------------
54
- **ライブラリ利用ガイド(Library Usage)**
55
-
56
- 下記はライブラリの代表的な使い方(TypeScript)です。詳しい実装は各ファイルを参照してください。
57
-
58
- 例: `VirtualFS` を初期化してローカル編集を push する
59
-
60
- ```ts
61
- import VirtualFS from './src/virtualfs/virtualfs'
62
- import GitHubAdapter from './src/git/githubAdapter'
63
-
64
- async function example() {
65
- const vfs = new VirtualFS({ storageDir: '.apigit' })
66
- await vfs.init()
67
-
68
- // ワークスペース編集
69
- await vfs.writeWorkspace('foo.txt', 'hello')
70
-
71
- // 変更セット取得
72
- const changes = await vfs.getChangeSet()
73
-
74
- // GitHub アダプタを使って push
75
- const gh = new GitHubAdapter({ owner: 'ORG', repo: 'REPO', token: process.env.GH_TOKEN })
76
- const res = await vfs.push({ parentSha: vfs.getIndex().head, message: 'update', changes }, gh as any)
77
- console.log('commitSha', res.commitSha)
78
- }
79
- ```
80
-
81
- API の概略(主要メソッド)
82
- - `new VirtualFS(options?)` - オプション: `{ storageDir?: string, backend?: StorageBackend }`
83
- - `init()` - バックエンド初期化と index 読み込み
84
- - `writeWorkspace(filepath, content)` - ワークスペースにファイルを書き込む
85
- - `deleteWorkspace(filepath)` - ワークスペース上のファイルを削除(トゥームストーン管理)
86
- - `renameWorkspace(from, to)` - rename(内部では delete + create)
87
- - `readWorkspace(filepath)` - ワークスペース/ベースから内容を読み出す
88
- - `applyBaseSnapshot(snapshot, headSha)` - リモートスナップショットを適用
89
- - `getIndex()` - 現在の index を返す
90
- - `listPaths()` - 登録パス一覧
91
- - `getChangeSet()` - create/update/delete の配列を生成
92
- - `pull(remoteHead, baseSnapshot)` - リモート差分取り込み(conflicts を返す)
93
- - `push(input, adapter?)` - 変更をコミットし(adapter があれば)リモートへ反映
94
-
95
- GitAdapter インターフェース(`src/git/adapter.ts`)
96
- - `createBlobs(changes, concurrency?)` -> Promise<Record<string,string>>
97
- - `createTree(changes, baseTreeSha?)` -> Promise<string>
98
- - `createCommit(message, parentSha, treeSha)` -> Promise<string>
99
- - `updateRef(ref, commitSha, force?)` -> Promise<void>
100
-
101
- 実装済みアダプタの注意点:
102
- - `GitHubAdapter` は `blob/tree/commit` フローを実装し、HTTP 再試行ロジックを内蔵しています(5xx, 429 のリトライ等)。実装は [src/git/githubAdapter.ts](src/git/githubAdapter.ts) を参照してください。
103
- - GitLab 用実装はリポジトリ内に存在しますが、環境差異により API の振る舞いが異なるため本番運用前に検証してください。⚠️
104
-
105
- --------------------------------------------------
106
- **開発セットアップ**
107
- - Node: 任意の recent Node.js(ESM サポート済み)
108
- - 実行手順
109
-
110
- ```bash
111
- git clone <repo>
112
- cd APIGitWorkspace01
113
- npm ci
114
- ```
115
-
116
- - コマンド一覧
117
- - `npm run test` : ユニットテスト(Jest)
118
- - `npm run test:e2e` : Playwright E2E
119
- - `npm run lint` : ESLint
120
- - `npm run build` : TypeScript ビルド
121
-
122
- テスト関連の注意:
123
- - Jest は ESM を扱うため `node --experimental-vm-modules` を使用するスクリプトが package.json に設定されています。
124
-
125
- --------------------------------------------------
126
- **現在のステータス**
127
- - 実装済み: `VirtualFS` のコア機能(差分生成、push/pull シミュレーション、index 管理)、`GitHubAdapter` の主要な API 呼び出し。
128
- - テスト: unit テストと一部の E2E テストが含まれています(`test/` 配下)。
129
- - 未確定/要検証: 外部サービス(GitLab)の細かい API 挙動、production 用のエラー・認可ポリシー。
130
-
131
- --------------------------------------------------
132
- **ライセンスとメタデータ**
133
- - package name: `browser-git-ops`
134
- - version: `0.0.0`
135
- - module type: CommonJS (`type: commonjs`)
136
- - License: MIT License
137
-
138
- --------------------------------------------------
139
- 追加で欲しいもの
140
- - サンプルユースケースを示す小さなサンプルリポジトリまたは `examples/` ディレクトリ
141
-
142
-
143
- --------------------------------------------------
144
- 貢献・問い合わせ
145
- - PR/Issue を歓迎します。まず issue を立て、簡単な実装提案(変更点の概要)を添えてください。
146
-
1
+ # browser-git-ops
2
+
3
+ **目的**: ブラウザネイティブ環境(OPFS + Github/Gitlab APIs)で動作する軽量な Git 操作ライブラリを提供します。VirtualFS によるローカル差分生成と、GitHub/GitLab 向けのアダプタを通じたリモート操作を抽象化します。
4
+
5
+ **主な特徴**
6
+ - **仮想ファイルシステム (VirtualFS)**: ローカルワークスペースとベーススナップショットを管理し、変更セット(create/update/delete)を生成します。
7
+ - **Git アダプタ抽象**: `GitAdapter` インターフェースに準拠するアダプタで GitHub/GitLab API を操作できます(サンプル実装あり)。
8
+ - **Idempotent push**: commitKey による冪等処理サポート。
9
+ - **衝突検知とマージ補助**: リモート差分取り込み時にローカルの未コミット変更を検出して conflicts を報告します。
10
+
11
+ **注意(⚠️)**: 実装はユーティリティ/ライブラリ向けで、環境やアクセストークンの管理、エラーハンドリング方針は利用側で制御してください。
12
+
13
+ **プロジェクト構成(抜粋)**
14
+ - **src/virtualfs/virtualfs.ts**: VirtualFS 本体(初期化、read/write、push/pull、差分生成) - [src/virtualfs/virtualfs.ts](src/virtualfs/virtualfs.ts)
15
+ - **src/virtualfs/persistence.ts**: ストレージバックエンドの抽象と Node 用実装 - [src/virtualfs/persistence.ts](src/virtualfs/persistence.ts)
16
+ - **src/git/adapter.ts**: `GitAdapter` インターフェース定義 - [src/git/adapter.ts](src/git/adapter.ts)
17
+ - **src/git/githubAdapter.ts**: GitHub 用アダプタ(blob/tree/commit フロー、再試行ロジック) - [src/git/githubAdapter.ts](src/git/githubAdapter.ts)
18
+ - **test/**: ユニット/E2E テスト群(Jest / Playwright) - [test](test)
19
+
20
+ **技術スタック**
21
+ - TypeScript 5.x
22
+ - Node.js (ESM, `type: "module"`)
23
+ - テスト: Jest(unit) / Playwright(E2E)
24
+ - ビルド: `tsc`
25
+
26
+ --------------------------------------------------
27
+ **クイックスタート(開発用)**
28
+
29
+ 1. 依存インストール
30
+
31
+ ```bash
32
+ npm ci
33
+ ```
34
+
35
+ 2. ユニットテスト実行
36
+
37
+ ```bash
38
+ npm run test
39
+ ```
40
+
41
+ 3. E2E テスト(Playwright)
42
+
43
+ ```bash
44
+ npm run test:e2e
45
+ ```
46
+
47
+ 4. ビルド
48
+
49
+ ```bash
50
+ npm run build
51
+ ```
52
+
53
+ --------------------------------------------------
54
+ **ライブラリ利用ガイド(Library Usage)**
55
+
56
+ 下記はライブラリの代表的な使い方(TypeScript)です。詳しい実装は各ファイルを参照してください。
57
+
58
+ 例: `VirtualFS` を初期化してローカル編集を push する
59
+
60
+ ```ts
61
+ import VirtualFS from './src/virtualfs/virtualfs'
62
+ import GitHubAdapter from './src/git/githubAdapter'
63
+
64
+ async function example() {
65
+ const vfs = new VirtualFS({ storageDir: '.apigit' })
66
+ await vfs.init()
67
+
68
+ // ワークスペース編集
69
+ await vfs.writeWorkspace('foo.txt', 'hello')
70
+
71
+ // 変更セット取得
72
+ const changes = await vfs.getChangeSet()
73
+
74
+ // GitHub アダプタを使って push
75
+ const gh = new GitHubAdapter({ owner: 'ORG', repo: 'REPO', token: process.env.GH_TOKEN })
76
+ const res = await vfs.push({ parentSha: vfs.getIndex().head, message: 'update', changes }, gh as any)
77
+ console.log('commitSha', res.commitSha)
78
+ }
79
+ ```
80
+
81
+ API の概略(主要メソッド)
82
+ - `new VirtualFS(options?)` - オプション: `{ storageDir?: string, backend?: StorageBackend }`
83
+ - `init()` - バックエンド初期化と index 読み込み
84
+ - `writeWorkspace(filepath, content)` - ワークスペースにファイルを書き込む
85
+ - `deleteWorkspace(filepath)` - ワークスペース上のファイルを削除(トゥームストーン管理)
86
+ - `renameWorkspace(from, to)` - rename(内部では delete + create)
87
+ - `readWorkspace(filepath)` - ワークスペース/ベースから内容を読み出す
88
+ - `applyBaseSnapshot(snapshot, headSha)` - リモートスナップショットを適用
89
+ - `getIndex()` - 現在の index を返す
90
+ - `listPaths()` - 登録パス一覧
91
+ - `getChangeSet()` - create/update/delete の配列を生成
92
+ - `pull(remoteHead, baseSnapshot)` - リモート差分取り込み(conflicts を返す)
93
+ - `push(input, adapter?)` - 変更をコミットし(adapter があれば)リモートへ反映
94
+
95
+ GitAdapter インターフェース(`src/git/adapter.ts`)
96
+ - `createBlobs(changes, concurrency?)` -> Promise<Record<string,string>>
97
+ - `createTree(changes, baseTreeSha?)` -> Promise<string>
98
+ - `createCommit(message, parentSha, treeSha)` -> Promise<string>
99
+ - `updateRef(ref, commitSha, force?)` -> Promise<void>
100
+
101
+ 実装済みアダプタの注意点:
102
+ - `GitHubAdapter` は `blob/tree/commit` フローを実装し、HTTP 再試行ロジックを内蔵しています(5xx, 429 のリトライ等)。実装は [src/git/githubAdapter.ts](src/git/githubAdapter.ts) を参照してください。
103
+ - GitLab 用実装はリポジトリ内に存在しますが、環境差異により API の振る舞いが異なるため本番運用前に検証してください。⚠️
104
+
105
+ --------------------------------------------------
106
+ **開発セットアップ**
107
+ - Node: 任意の recent Node.js(ESM サポート済み)
108
+ - 実行手順
109
+
110
+ ```bash
111
+ git clone <repo>
112
+ cd APIGitWorkspace01
113
+ npm ci
114
+ ```
115
+
116
+ - コマンド一覧
117
+ - `npm run test` : ユニットテスト(Jest)
118
+ - `npm run test:e2e` : Playwright E2E
119
+ - `npm run lint` : ESLint
120
+ - `npm run build` : TypeScript ビルド
121
+
122
+ テスト関連の注意:
123
+ - Jest は ESM を扱うため `node --experimental-vm-modules` を使用するスクリプトが package.json に設定されています。
124
+
125
+ --------------------------------------------------
126
+ **現在のステータス**
127
+ - 実装済み: `VirtualFS` のコア機能(差分生成、push/pull シミュレーション、index 管理)、`GitHubAdapter` の主要な API 呼び出し。
128
+ - テスト: unit テストと一部の E2E テストが含まれています(`test/` 配下)。
129
+ - 未確定/要検証: 外部サービス(GitLab)の細かい API 挙動、production 用のエラー・認可ポリシー。
130
+
131
+ --------------------------------------------------
132
+ **ライセンスとメタデータ**
133
+ - package name: `browser-git-ops`
134
+ - version: `0.0.0`
135
+ - module type: CommonJS (`type: commonjs`)
136
+ - License: MIT License
137
+
138
+ --------------------------------------------------
139
+ 追加で欲しいもの
140
+ - サンプルユースケースを示す小さなサンプルリポジトリまたは `examples/` ディレクトリ
141
+
142
+
143
+ --------------------------------------------------
144
+ 貢献・問い合わせ
145
+ - PR/Issue を歓迎します。まず issue を立て、簡単な実装提案(変更点の概要)を添えてください。
146
+
@@ -1 +1 @@
1
- {"version":3,"file":"githubAdapter.d.ts","sourceRoot":"","sources":["../../src/git/githubAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAGtC,KAAK,SAAS,GAAG;IACf,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,KAAK;CAAG;AAE5C;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;CAAG;AAU/C;;;;;;;GAOG;AAEH,iBAAe,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,SAAI,EAAE,SAAS,SAAM,qBAcjG;AAED,iBAAS,cAAc,CAAC,MAAM,EAAE,MAAM,WAErC;AAED,iBAAS,mBAAmB,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,UAI9E;AAED,iBAAe,wBAAwB,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,qBAQlF;AAED;;;;;GAKG;AAEH,iBAAS,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,SAAI,gBAc3F;AAED,qBAAa,aAAc,YAAW,UAAU;IAMlC,OAAO,CAAC,IAAI;IALxB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,eAAe,CAAqF;IAE5G,OAAO,CAAC,SAAS,CAAiC;gBAC9B,IAAI,EAAE,SAAS;IAU7B,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,WAAW,SAAI;IAqB3C,UAAU,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,WAAW,CAAC,EAAE,MAAM;IAkB/C,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAQhE,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,UAAQ;CAQ9D;AAED,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,CAAA;AAC5G,eAAe,aAAa,CAAA"}
1
+ {"version":3,"file":"githubAdapter.d.ts","sourceRoot":"","sources":["../../src/git/githubAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAGtC,KAAK,SAAS,GAAG;IACf,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,KAAK;CAAG;AAE5C;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;CAAG;AAU/C;;;;;;;GAOG;AAEH,iBAAe,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,SAAI,EAAE,SAAS,SAAM,qBAcjG;AAED,iBAAS,cAAc,CAAC,MAAM,EAAE,MAAM,WAErC;AAED,iBAAS,mBAAmB,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,UAI9E;AAED,iBAAe,wBAAwB,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,qBAQlF;AAED;;;;;GAKG;AAEH,iBAAS,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,SAAI,gBAc3F;AAED,qBAAa,aAAc,YAAW,UAAU;IAMlC,OAAO,CAAC,IAAI;IALxB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,eAAe,CAAqF;IAE5G,OAAO,CAAC,SAAS,CAAiC;gBAC9B,IAAI,EAAE,SAAS;IAU7B,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,WAAW,SAAI;IAqB3C,UAAU,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,WAAW,CAAC,EAAE,MAAM;IAkB/C,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAQhE,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,UAAQ;CAQ9D;AAED,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,CAAA;AAC5G,eAAe,aAAa,CAAA"}
@@ -50,67 +50,67 @@ async function installMockApi(page, initialFiles = {}) {
50
50
  };
51
51
  }
52
52
  // Simple in-page VirtualFS implementation used by tests
53
- const vfsScript = `(() => {
54
- const base = {}; // files that reflect remote base
55
- const workspace = {}; // pending edits
56
- const tombstone = new Set();
57
- let head = 'initial';
58
-
59
- async function pull() {
60
- const res = await fetch('http://example.com/api/pull');
61
- if (!res.ok) throw new Error('pull failed');
62
- const body = await res.json();
63
- for (const k of Object.keys(base)) delete base[k];
64
- for (const [k,v] of Object.entries(body.files)) base[k]=v;
65
- head = body.head;
66
- // clear workspace/tombstone on successful pull
67
- for (const k of Object.keys(workspace)) delete workspace[k];
68
- tombstone.clear();
69
- return { head };
70
- }
71
-
72
- async function push() {
73
- // compute actions from workspace/tombstone
74
- const actions = [];
75
- for (const k of Object.keys(workspace)) {
76
- if (!(k in base)) actions.push({ action: 'create', path: k, content: workspace[k] });
77
- else if (base[k] !== workspace[k]) actions.push({ action: 'update', path: k, content: workspace[k] });
78
- }
79
- for (const p of tombstone) actions.push({ action: 'delete', path: p });
80
- if (actions.length === 0) return { noop: true };
81
- const res = await fetch('http://example.com/api/commit', { method: 'POST', headers: {'content-type':'application/json'}, body: JSON.stringify({ actions, message: 'test commit' }) });
82
- if (!res.ok) throw new Error('push failed');
83
- const body = await res.json();
84
- // apply commit to base
85
- for (const a of actions) {
86
- if (a.action === 'create' || a.action === 'update') base[a.path] = a.content ?? '';
87
- else if (a.action === 'delete') delete base[a.path];
88
- }
89
- // clear workspace/tombstone
90
- for (const k of Object.keys(workspace)) delete workspace[k];
91
- tombstone.clear();
92
- head = body.commit.id;
93
- return { commit: body.commit };
94
- }
95
-
96
- return {
97
- readFile: (p) => {
98
- if (p in workspace) return workspace[p];
99
- if (p in base) return base[p];
100
- throw new Error('not found');
101
- },
102
- writeFile: (p, content) => { workspace[p] = content; tombstone.delete(p); },
103
- delete: (p) => { delete workspace[p]; if (p in base) tombstone.add(p); },
104
- rename: (from, to) => {
105
- if (from in workspace) { workspace[to] = workspace[from]; delete workspace[from]; }
106
- else if (from in base) { tombstone.add(from); workspace[to] = base[from]; }
107
- },
108
- status: () => ({ changed: Object.keys(workspace), deleted: Array.from(tombstone), conflicted: [] }),
109
- pull, push,
110
- _debug_getBase: () => ({ ...base }),
111
- _debug_getWorkspace: () => ({ ...workspace }),
112
- _debug_getTombstone: () => Array.from(tombstone),
113
- };
53
+ const vfsScript = `(() => {
54
+ const base = {}; // files that reflect remote base
55
+ const workspace = {}; // pending edits
56
+ const tombstone = new Set();
57
+ let head = 'initial';
58
+
59
+ async function pull() {
60
+ const res = await fetch('http://example.com/api/pull');
61
+ if (!res.ok) throw new Error('pull failed');
62
+ const body = await res.json();
63
+ for (const k of Object.keys(base)) delete base[k];
64
+ for (const [k,v] of Object.entries(body.files)) base[k]=v;
65
+ head = body.head;
66
+ // clear workspace/tombstone on successful pull
67
+ for (const k of Object.keys(workspace)) delete workspace[k];
68
+ tombstone.clear();
69
+ return { head };
70
+ }
71
+
72
+ async function push() {
73
+ // compute actions from workspace/tombstone
74
+ const actions = [];
75
+ for (const k of Object.keys(workspace)) {
76
+ if (!(k in base)) actions.push({ action: 'create', path: k, content: workspace[k] });
77
+ else if (base[k] !== workspace[k]) actions.push({ action: 'update', path: k, content: workspace[k] });
78
+ }
79
+ for (const p of tombstone) actions.push({ action: 'delete', path: p });
80
+ if (actions.length === 0) return { noop: true };
81
+ const res = await fetch('http://example.com/api/commit', { method: 'POST', headers: {'content-type':'application/json'}, body: JSON.stringify({ actions, message: 'test commit' }) });
82
+ if (!res.ok) throw new Error('push failed');
83
+ const body = await res.json();
84
+ // apply commit to base
85
+ for (const a of actions) {
86
+ if (a.action === 'create' || a.action === 'update') base[a.path] = a.content ?? '';
87
+ else if (a.action === 'delete') delete base[a.path];
88
+ }
89
+ // clear workspace/tombstone
90
+ for (const k of Object.keys(workspace)) delete workspace[k];
91
+ tombstone.clear();
92
+ head = body.commit.id;
93
+ return { commit: body.commit };
94
+ }
95
+
96
+ return {
97
+ readFile: (p) => {
98
+ if (p in workspace) return workspace[p];
99
+ if (p in base) return base[p];
100
+ throw new Error('not found');
101
+ },
102
+ writeFile: (p, content) => { workspace[p] = content; tombstone.delete(p); },
103
+ delete: (p) => { delete workspace[p]; if (p in base) tombstone.add(p); },
104
+ rename: (from, to) => {
105
+ if (from in workspace) { workspace[to] = workspace[from]; delete workspace[from]; }
106
+ else if (from in base) { tombstone.add(from); workspace[to] = base[from]; }
107
+ },
108
+ status: () => ({ changed: Object.keys(workspace), deleted: Array.from(tombstone), conflicted: [] }),
109
+ pull, push,
110
+ _debug_getBase: () => ({ ...base }),
111
+ _debug_getWorkspace: () => ({ ...workspace }),
112
+ _debug_getTombstone: () => Array.from(tombstone),
113
+ };
114
114
  })();`;
115
115
  test_1.test.describe('VirtualFS E2E (mocked API)', () => {
116
116
  test_1.test.beforeEach(async ({ page }) => {
@@ -93,8 +93,9 @@ export declare class VirtualFS {
93
93
  * @returns {TombstoneEntry[]}
94
94
  */
95
95
  /**
96
- *
97
- */
96
+ * ワークスペースとインデックスから変更セットを生成します。
97
+ * @returns {Promise<Array<{type:string,path:string,content?:string,baseSha?:string}>>} 変更リスト
98
+ */
98
99
  getChangeSet(): Promise<({
99
100
  type: 'create';
100
101
  path: string;
@@ -1 +1 @@
1
- {"version":3,"file":"virtualfs.d.ts","sourceRoot":"","sources":["../../src/virtualfs/virtualfs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AACnD,OAAO,EAAE,cAAc,EAAiB,MAAM,eAAe,CAAA;AAE7D;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,IAAI,CAAsD;IAClE,OAAO,CAAC,SAAS,CAAsD;IACvE,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,KAAK,CAAuC;IACpD,OAAO,CAAC,OAAO,CAAgB;IAE/B;;OAEG;gBACS,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,cAAc,CAAA;KAAE;IAOvE;;;;OAIG;IACH,OAAO,CAAC,KAAK;IAIb;;;OAGG;IACG,IAAI;IAKV;;;OAGG;YACW,SAAS;IAmBvB;;;OAGG;YACW,SAAS;IAIvB;;OAEG;IACH;;;;;OAKG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAkBtD;;;;OAIG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM;IAqBtC;;;;OAIG;IACG,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAa9C;;;;OAIG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM;IAWpC;;;;;OAKG;IACG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM;IA2BzE;;;OAGG;IACH,QAAQ,IAAI,SAAS;IAIrB;;;OAGG;IACH,SAAS,IAAI,MAAM,EAAE;IAIrB;;;OAGG;IACH,aAAa,IAAI,cAAc,EAAE;IAIjC;;;OAGG;IAEH;;OAEG;IACG,YAAY;cAGJ,QAAQ;cAAQ,MAAM;iBAAW,MAAM;;cACvC,QAAQ;cAAQ,MAAM;iBAAW,MAAM;;;cACvC,QAAQ;cAAQ,MAAM;iBAAW,MAAM;;IAQrD;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAM9B;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAOhC;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAWhC;;;OAGG;IACH,OAAO,CAAC,2BAA2B;IAWnC;;;;OAIG;YACW,iBAAiB;IAS/B;;;OAGG;YACW,gBAAgB;IAa9B;;;OAGG;YACW,qBAAqB;IAkBnC;;;;OAIG;YACW,mBAAmB;IAqBjC;;;OAGG;YACW,qBAAqB;IAYnC;;;OAGG;YACW,gBAAgB;IAe9B;;;OAGG;YACW,mBAAmB;IAkBjC;;;;;OAKG;IACG,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;;;IA6BnE;;;;;OAKG;IACG,IAAI,CAAC,KAAK,EAAE,OAAO,SAAS,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,OAAO,gBAAgB,EAAE,UAAU;;;CAkD/F;AAED,eAAe,SAAS,CAAA"}
1
+ {"version":3,"file":"virtualfs.d.ts","sourceRoot":"","sources":["../../src/virtualfs/virtualfs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AACnD,OAAO,EAAE,cAAc,EAAiB,MAAM,eAAe,CAAA;AAE7D;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,IAAI,CAAsD;IAClE,OAAO,CAAC,SAAS,CAAsD;IACvE,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,KAAK,CAAuC;IACpD,OAAO,CAAC,OAAO,CAAgB;IAE/B;;OAEG;gBACS,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,cAAc,CAAA;KAAE;IAOvE;;;;OAIG;IACH,OAAO,CAAC,KAAK;IAIb;;;OAGG;IACG,IAAI;IAKV;;;OAGG;YACW,SAAS;IAmBvB;;;OAGG;YACW,SAAS;IAIvB;;OAEG;IACH;;;;;OAKG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAkBtD;;;;OAIG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM;IAqBtC;;;;OAIG;IACG,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAa9C;;;;OAIG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM;IAWpC;;;;;OAKG;IACG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM;IA2BzE;;;OAGG;IACH,QAAQ,IAAI,SAAS;IAIrB;;;OAGG;IACH,SAAS,IAAI,MAAM,EAAE;IAIrB;;;OAGG;IACH,aAAa,IAAI,cAAc,EAAE;IAIjC;;;OAGG;IAEH;;;QAGI;IACI,YAAY;cAGN,QAAQ;cAAQ,MAAM;iBAAW,MAAM;;cACvC,QAAQ;cAAQ,MAAM;iBAAW,MAAM;;;cACvC,QAAQ;cAAQ,MAAM;iBAAW,MAAM;;IAQrD;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAM9B;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAOhC;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAWhC;;;OAGG;IACH,OAAO,CAAC,2BAA2B;IAWnC;;;;OAIG;YACW,iBAAiB;IAS/B;;;OAGG;YACW,gBAAgB;IAa9B;;;OAGG;YACW,qBAAqB;IAkBnC;;;;OAIG;YACW,mBAAmB;IAqBjC;;;OAGG;YACW,qBAAqB;IAYnC;;;OAGG;YACW,gBAAgB;IAe9B;;;OAGG;YACW,mBAAmB;IAkBjC;;;;;OAKG;IACG,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;;;IA6BnE;;;;;OAKG;IACG,IAAI,CAAC,KAAK,EAAE,OAAO,SAAS,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,OAAO,gBAAgB,EAAE,UAAU;;;CAkD/F;AAED,eAAe,SAAS,CAAA"}
@@ -218,8 +218,9 @@ class VirtualFS {
218
218
  * @returns {TombstoneEntry[]}
219
219
  */
220
220
  /**
221
- *
222
- */
221
+ * ワークスペースとインデックスから変更セットを生成します。
222
+ * @returns {Promise<Array<{type:string,path:string,content?:string,baseSha?:string}>>} 変更リスト
223
+ */
223
224
  async getChangeSet() {
224
225
  const changes = [];
225
226
  changes.push(...this._changesFromTombstones());
@@ -467,7 +468,6 @@ class VirtualFS {
467
468
  // If adapter supports createCommitWithActions (GitLab style), use it directly
468
469
  if (adapter.createCommitWithActions) {
469
470
  // ensure message contains commitKey
470
- ;
471
471
  input.message = messageWithKey;
472
472
  const res = await this._pushWithActions(adapter, input, branch);
473
473
  // record commitKey in index metadata
@@ -475,7 +475,6 @@ class VirtualFS {
475
475
  return res;
476
476
  }
477
477
  // Fallback to GitHub-style flow: delegate to helper
478
- ;
479
478
  input.message = messageWithKey;
480
479
  const res = await this._pushWithGitHubFlow(adapter, input, branch);
481
480
  this.index.lastCommitKey = input.commitKey;
package/package.json CHANGED
@@ -1,47 +1,47 @@
1
- {
2
- "name": "browser-git-ops",
3
- "version": "0.0.0",
4
- "type": "commonjs",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "description": "A browser-native Git operations library built with OPFS and Web APIs.",
8
- "repository": {
9
- "type": "git",
10
- "url": "git+https://github.com/nojaja/APIGitWorkspace.git"
11
- },
12
- "bugs": {
13
- "url": "https://github.com/nojaja/APIGitWorkspace/issues"
14
- },
15
- "homepage": "https://github.com/nojaja/APIGitWorkspace#readme",
16
- "keywords": ["virtualfs", "git", "github", "vfs", "apigit"],
17
- "author": "nojaja <free.riccia@gmail.com> (https://github.com/nojaja)",
18
- "license": "MIT",
19
- "files": [
20
- "dist",
21
- "README.md",
22
- "LICENSE"
23
- ],
24
- "scripts": {
25
- "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --runInBand",
26
- "pretest:e2e": "npm run build",
27
- "test:e2e": "playwright test --config=playwright.config.cjs",
28
- "test:ci": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --coverage --runInBand",
29
- "lint": "eslint \"src/**/*.{ts,js}\" --config .eslintrc.cjs",
30
- "depcruise": "depcruise --config .dependency-cruiser.js src || exit 0",
31
- "build": "tsc -p tsconfig.json && tsc -p tsconfig.e2e.json"
32
- },
33
- "devDependencies": {
34
- "@playwright/test": "^1.40.0",
35
- "@types/jest": "^29.5.2",
36
- "@typescript-eslint/eslint-plugin": "^6.10.0",
37
- "@typescript-eslint/parser": "^6.10.0",
38
- "dependency-cruiser": "^17.3.6",
39
- "eslint": "^8.45.0",
40
- "eslint-plugin-jsdoc": "^62.1.0",
41
- "eslint-plugin-sonarjs": "^0.16.0",
42
- "jest": "^29.6.1",
43
- "ts-jest": "^29.1.0",
44
- "typedoc": "^0.25.0",
45
- "typescript": "5.3.3"
46
- }
47
- }
1
+ {
2
+ "name": "browser-git-ops",
3
+ "version": "0.0.1",
4
+ "type": "commonjs",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "description": "A browser-native Git operations library built with OPFS and Web APIs.",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/nojaja/browser-git-ops.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/nojaja/browser-git-ops/issues"
14
+ },
15
+ "homepage": "https://github.com/nojaja/browser-git-ops#readme",
16
+ "keywords": ["virtualfs", "git", "github", "vfs", "apigit"],
17
+ "author": "nojaja <free.riccia@gmail.com> (https://github.com/nojaja)",
18
+ "license": "MIT",
19
+ "files": [
20
+ "dist",
21
+ "README.md",
22
+ "LICENSE"
23
+ ],
24
+ "scripts": {
25
+ "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --runInBand",
26
+ "pretest:e2e": "npm run build",
27
+ "test:e2e": "playwright test --config=playwright.config.cjs",
28
+ "test:ci": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --coverage --runInBand",
29
+ "lint": "eslint \"src/**/*.{ts,js}\" --config .eslintrc.cjs",
30
+ "depcruise": "depcruise --config .dependency-cruiser.cjs src || exit 0",
31
+ "build": "tsc -p tsconfig.json && tsc -p tsconfig.e2e.json"
32
+ },
33
+ "devDependencies": {
34
+ "@playwright/test": "^1.40.0",
35
+ "@types/jest": "^29.5.2",
36
+ "@typescript-eslint/eslint-plugin": "^6.10.0",
37
+ "@typescript-eslint/parser": "^6.10.0",
38
+ "dependency-cruiser": "^17.3.6",
39
+ "eslint": "^8.45.0",
40
+ "eslint-plugin-jsdoc": "^62.1.0",
41
+ "eslint-plugin-sonarjs": "^0.16.0",
42
+ "jest": "^29.6.1",
43
+ "ts-jest": "^29.1.0",
44
+ "typedoc": "^0.25.0",
45
+ "typescript": "5.3.3"
46
+ }
47
+ }