browser-git-ops 0.0.4 → 0.0.7
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 +346 -67
- package/dist/git/abstractAdapter.d.ts +25 -21
- package/dist/git/abstractAdapter.d.ts.map +1 -1
- package/dist/git/githubAdapter.d.ts +16 -83
- package/dist/git/githubAdapter.d.ts.map +1 -1
- package/dist/git/gitlabAdapter.d.ts +26 -102
- package/dist/git/gitlabAdapter.d.ts.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1742 -1341
- package/dist/index.js.map +3 -3
- package/dist/index.mjs +1739 -1338
- package/dist/index.mjs.map +3 -3
- package/dist/virtualfs/changeTracker.d.ts +1 -0
- package/dist/virtualfs/changeTracker.d.ts.map +1 -1
- package/dist/virtualfs/conflictManager.d.ts +3 -1
- package/dist/virtualfs/conflictManager.d.ts.map +1 -1
- package/dist/virtualfs/indexedDatabaseStorage.d.ts.map +1 -1
- package/dist/virtualfs/inmemoryStorage.d.ts.map +1 -1
- package/dist/virtualfs/localChangeApplier.d.ts +6 -3
- package/dist/virtualfs/localChangeApplier.d.ts.map +1 -1
- package/dist/virtualfs/localFileManager.d.ts.map +1 -1
- package/dist/virtualfs/metadataManager.d.ts +0 -4
- package/dist/virtualfs/metadataManager.d.ts.map +1 -1
- package/dist/virtualfs/opfsStorage.d.ts.map +1 -1
- package/dist/virtualfs/remoteSynchronizer.d.ts +117 -20
- package/dist/virtualfs/remoteSynchronizer.d.ts.map +1 -1
- package/dist/virtualfs/storageBackend.d.ts +18 -18
- package/dist/virtualfs/storageBackend.d.ts.map +1 -1
- package/dist/virtualfs/types.d.ts +5 -4
- package/dist/virtualfs/types.d.ts.map +1 -1
- package/dist/virtualfs/utils/urlParser.d.ts +14 -0
- package/dist/virtualfs/utils/urlParser.d.ts.map +1 -0
- package/dist/virtualfs/virtualfs.d.ts +254 -42
- package/dist/virtualfs/virtualfs.d.ts.map +1 -1
- package/package.json +9 -10
package/README.md
CHANGED
|
@@ -1,119 +1,398 @@
|
|
|
1
|
-
[](https://deepwiki.com/nojaja/browser-git-ops)
|
|
1
|
+
[](https://deepwiki.com/nojaja/browser-git-ops) [](https://github.com/nojaja/browser-git-ops/blob/main/README_ja.md)
|
|
2
2
|
|
|
3
3
|
# browser-git-ops
|
|
4
4
|
|
|
5
5
|
A browser-native Git operations library that provides a VirtualFS and platform adapters for GitHub and GitLab. It implements multiple persistent backends (OPFS, IndexedDB, and an in-memory backend) and abstracts them behind a common VirtualFS API.
|
|
6
6
|
|
|
7
|
-
- Live Demo
|
|
7
|
+
- **Live Demo**: https://nojaja.github.io/browser-git-ops/
|
|
8
8
|
|
|
9
|
-
**[
|
|
9
|
+
**[English](./README.md)** | **[日本語](./README_ja.md)**
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
- VirtualFS: local workspace snapshoting and change-set generation (create/update/delete).
|
|
13
|
-
- Multiple backends: `OpfsStorage` (OPFS), `IndexedDatabaseStorage` (IndexedDB), and `InMemoryStorage` (testing).
|
|
14
|
-
- Platform adapters: `GitHubAdapter` and `GitLabAdapter` implementing common push/fetch flows via Web APIs, enabling cross-origin operations without CORS proxy workarounds.
|
|
11
|
+
## Overview
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
- Core VirtualFS functionality implemented (delta generation, index management, local edits).
|
|
18
|
-
- Persistence backends for OPFS and IndexedDB implemented.
|
|
19
|
-
- GitHubAdapter includes primary push flow; GitLab adapter exists but may require extra environment verification.
|
|
13
|
+

|
|
20
14
|
|
|
21
|
-
|
|
15
|
+
## Key Features
|
|
16
|
+
|
|
17
|
+
- **VirtualFS**: Local workspace snapshotting and change-set generation (create/update/delete)
|
|
18
|
+
- **Multiple Storage Backends**:
|
|
19
|
+
- `OpfsStorage` - Origin Private File System (OPFS)
|
|
20
|
+
- `IndexedDatabaseStorage` - IndexedDB for broader browser compatibility
|
|
21
|
+
- `InMemoryStorage` - In-memory storage for testing
|
|
22
|
+
- **Platform Adapters**: `GitHubAdapter` and `GitLabAdapter` implementing common push/pull flows via Web APIs
|
|
23
|
+
- **CORS-Free Operations**: Direct API integration without proxy workarounds
|
|
24
|
+
- **TypeScript Support**: Fully typed API with TypeScript definitions
|
|
25
|
+
|
|
26
|
+
## v0.0.5: FS-compatible API
|
|
27
|
+
|
|
28
|
+
- Adds Node-like filesystem methods on `VirtualFS`: `stat`, `unlink`, `mkdir`, `rmdir`, `readdir`.
|
|
29
|
+
- `Stats` objects now include Git identifiers when available (`gitBlobSha`, `gitCommitSha`).
|
|
30
|
+
- `deleteFile` is removed from the public API; use `unlink` instead.
|
|
31
|
+
|
|
32
|
+
## Status
|
|
33
|
+
|
|
34
|
+
- ✅ Core VirtualFS functionality (delta generation, index management, local edits)
|
|
35
|
+
- ✅ Persistence backends for OPFS and IndexedDB
|
|
36
|
+
- ✅ GitHubAdapter with primary push/pull flows
|
|
37
|
+
- ✅ GitLabAdapter with primary push/pull flows
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
### For Library Consumers (npm)
|
|
22
42
|
|
|
23
43
|
```bash
|
|
24
|
-
npm
|
|
44
|
+
npm install browser-git-ops
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### For Development
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
git clone https://github.com/nojaja/browser-git-ops.git
|
|
51
|
+
cd browser-git-ops
|
|
52
|
+
npm ci
|
|
25
53
|
```
|
|
26
54
|
|
|
27
|
-
Usage
|
|
55
|
+
## Usage
|
|
28
56
|
|
|
29
|
-
|
|
57
|
+
### Basic Example
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
30
60
|
import { VirtualFS, OpfsStorage, GitHubAdapter } from 'browser-git-ops'
|
|
31
61
|
|
|
32
62
|
async function example() {
|
|
33
|
-
|
|
63
|
+
// 1. Initialize VirtualFS with OPFS backend
|
|
64
|
+
const backend = new OpfsStorage('appname','my-workspace')
|
|
34
65
|
const vfs = new VirtualFS({ backend })
|
|
35
66
|
await vfs.init()
|
|
36
|
-
await vfs.setAdapter(null, { type: 'gitlab', opts: { projectId: 'ORG', host: 'HOST', token: 'token', branch: 'main' } })
|
|
37
67
|
|
|
68
|
+
// 2. Configure adapter (GitHub or GitLab)
|
|
69
|
+
await vfs.setAdapter(null, {
|
|
70
|
+
type: 'github',
|
|
71
|
+
opts: {
|
|
72
|
+
owner: 'your-username',
|
|
73
|
+
repo: 'your-repo',
|
|
74
|
+
token: 'your-github-token',
|
|
75
|
+
branch: 'main'
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
// 3. Pull latest content from remote
|
|
38
80
|
await vfs.pull()
|
|
39
|
-
const list = await vfs.listPaths()
|
|
40
|
-
await vfs.writeFile('README.md', 'hello world')
|
|
41
|
-
const changes = await vfs.getChangeSet()
|
|
42
81
|
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
|
|
82
|
+
// 4. List files (use the FS-compatible API)
|
|
83
|
+
const files = await vfs.readdir('.')
|
|
84
|
+
console.log('Files:', files)
|
|
85
|
+
|
|
86
|
+
// 5. Make local changes
|
|
87
|
+
await vfs.writeFile('README.md', '# Hello World')
|
|
88
|
+
await vfs.writeFile('docs/guide.md', '## Getting Started')
|
|
89
|
+
|
|
90
|
+
// 6. Stat a file (Stats includes gitBlobSha/gitCommitSha when available)
|
|
91
|
+
// 6. Stat a file — returned object implements fs.Stats-like shape
|
|
92
|
+
// When the file is tracked by a configured adapter, the returned
|
|
93
|
+
// stats may include Git-specific identifiers: gitBlobSha, gitCommitSha, gitRef.
|
|
94
|
+
const s = await vfs.stat('README.md')
|
|
95
|
+
console.log('size=', s.size, 'isFile=', s.isFile())
|
|
96
|
+
// Git-specific fields (may be undefined for non-tracked files):
|
|
97
|
+
console.log('gitBlobSha=', s.gitBlobSha, 'gitCommitSha=', s.gitCommitSha, 'gitRef=', s.gitRef)
|
|
98
|
+
|
|
99
|
+
// 7. Delete a file (use unlink instead of deleteFile)
|
|
100
|
+
await vfs.unlink('docs/guide.md')
|
|
101
|
+
|
|
102
|
+
// 8. Create/remove directories
|
|
103
|
+
await vfs.mkdir('notes')
|
|
104
|
+
await vfs.rmdir('notes', { recursive: true })
|
|
105
|
+
// 9. Get change set and push
|
|
106
|
+
const changes = await vfs.getChangeSet()
|
|
107
|
+
console.log('Changes:', changes)
|
|
108
|
+
|
|
109
|
+
const index = await vfs.getIndex()
|
|
110
|
+
const result = await vfs.push({
|
|
111
|
+
parentSha: index.head,
|
|
112
|
+
message: 'Update documentation',
|
|
113
|
+
changes: changes
|
|
114
|
+
})
|
|
115
|
+
console.log('Push result:', result)
|
|
46
116
|
}
|
|
47
117
|
```
|
|
48
118
|
|
|
49
|
-
|
|
119
|
+
### Using IndexedDB Backend
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { VirtualFS, IndexedDatabaseStorage } from 'browser-git-ops'
|
|
123
|
+
|
|
124
|
+
const backend = new IndexedDatabaseStorage('my-workspace')
|
|
125
|
+
const vfs = new VirtualFS({ backend })
|
|
126
|
+
await vfs.init()
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Using GitLab Adapter
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
await vfs.setAdapter(null, {
|
|
133
|
+
type: 'gitlab',
|
|
134
|
+
opts: {
|
|
135
|
+
projectId: 'username/project',
|
|
136
|
+
host: 'gitlab.com',
|
|
137
|
+
token: 'your-gitlab-token',
|
|
138
|
+
branch: 'main'
|
|
139
|
+
}
|
|
140
|
+
})
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Development
|
|
144
|
+
|
|
145
|
+
### Build
|
|
50
146
|
|
|
51
147
|
```bash
|
|
52
|
-
|
|
53
|
-
cd browser-git-ops
|
|
54
|
-
npm ci
|
|
148
|
+
npm run build # Build browser bundles and TypeScript definitions
|
|
55
149
|
```
|
|
56
150
|
|
|
57
|
-
|
|
151
|
+
This generates:
|
|
152
|
+
- `dist/index.js` - IIFE bundle for browser (global `APIGitLib`)
|
|
153
|
+
- `dist/index.mjs` - ESM bundle
|
|
154
|
+
- `dist/index.d.ts` - TypeScript definitions
|
|
155
|
+
|
|
156
|
+
### Testing
|
|
58
157
|
|
|
59
158
|
```bash
|
|
60
|
-
npm run
|
|
61
|
-
npm run test
|
|
62
|
-
npm run test:
|
|
159
|
+
npm run test # Unit tests (Jest)
|
|
160
|
+
npm run test:spec # Specification tests only
|
|
161
|
+
npm run test:coverage # Tests with coverage report
|
|
162
|
+
npm run test:e2e # E2E tests (Playwright)
|
|
63
163
|
npm run lint # ESLint
|
|
64
164
|
```
|
|
65
165
|
|
|
66
|
-
|
|
166
|
+
### Documentation
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
npm run docs # Generate TypeDoc documentation
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Project Structure
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
src/
|
|
176
|
+
├── index.ts # Package entry point
|
|
177
|
+
├── virtualfs/
|
|
178
|
+
│ ├── virtualfs.ts # VirtualFS core implementation
|
|
179
|
+
│ ├── opfsStorage.ts # OPFS storage backend
|
|
180
|
+
│ ├── indexedDatabaseStorage.ts # IndexedDB storage backend
|
|
181
|
+
│ ├── inmemoryStorage.ts # In-memory storage (for testing)
|
|
182
|
+
│ ├── changeTracker.ts # Change detection and tracking
|
|
183
|
+
│ ├── conflictManager.ts # Merge conflict resolution
|
|
184
|
+
│ ├── indexManager.ts # Index file management
|
|
185
|
+
│ └── types.ts # Type definitions
|
|
186
|
+
└── git/
|
|
187
|
+
├── abstractAdapter.ts # Base adapter interface
|
|
188
|
+
├── githubAdapter.ts # GitHub API adapter
|
|
189
|
+
└── gitlabAdapter.ts # GitLab API adapter
|
|
190
|
+
|
|
191
|
+
examples/ # Browser demo application
|
|
192
|
+
test/
|
|
193
|
+
├── unit/ # Jest unit tests
|
|
194
|
+
└── e2e/ # Playwright E2E tests
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Configuration
|
|
198
|
+
|
|
199
|
+
### GitHub Adapter
|
|
200
|
+
|
|
201
|
+
To use the GitHub adapter, you need:
|
|
202
|
+
- **Personal Access Token** with `repo` scope
|
|
203
|
+
- Repository owner and name
|
|
204
|
+
- Target branch (default: `main`)
|
|
205
|
+
|
|
206
|
+
### GitLab Adapter
|
|
207
|
+
|
|
208
|
+
To use the GitLab adapter, you need:
|
|
209
|
+
- **Personal Access Token** or **Project Access Token**
|
|
210
|
+
- Project ID (format: `username/project` or numeric ID)
|
|
211
|
+
- GitLab instance host (default: `gitlab.com`)
|
|
212
|
+
- Target branch (default: `main`)
|
|
213
|
+
|
|
214
|
+
### Browser Compatibility
|
|
215
|
+
|
|
216
|
+
- **OPFS**: Requires modern browsers with OPFS support (Chrome 102+, Edge 102+)
|
|
217
|
+
- **IndexedDB**: Broader compatibility, works in most modern browsers
|
|
218
|
+
- **CORS**: No proxy required - uses direct API authentication
|
|
219
|
+
|
|
220
|
+
## API Reference
|
|
221
|
+
|
|
222
|
+
- See [docs/typedoc-md/README.md](docs/typedoc-md/README.md).
|
|
223
|
+
|
|
224
|
+
### VirtualFS
|
|
225
|
+
|
|
226
|
+
Main class for file system operations.
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
class VirtualFS {
|
|
230
|
+
constructor(options?: { backend?: StorageBackend; logger?: Logger })
|
|
231
|
+
|
|
232
|
+
// Initialization
|
|
233
|
+
async init(): Promise<void>
|
|
234
|
+
|
|
235
|
+
// File Operations
|
|
236
|
+
async writeFile(path: string, content: string): Promise<void>
|
|
237
|
+
async readFile(path: string): Promise<string>
|
|
238
|
+
async deleteFile(path: string): Promise<void>
|
|
239
|
+
async renameFile(fromPath: string, toPath: string): Promise<void>
|
|
240
|
+
async listPaths(): Promise<string[]>
|
|
241
|
+
|
|
242
|
+
// Change Management
|
|
243
|
+
async getChangeSet(): Promise<ChangeItem[]>
|
|
244
|
+
async revertChanges(): Promise<void>
|
|
245
|
+
|
|
246
|
+
// Remote Synchronization
|
|
247
|
+
async setAdapter(meta: { type: 'github' | 'gitlab' | string, opts?: any}): Promise<void>
|
|
248
|
+
async getAdapter(): Promise<{ type: string, opts?: any } | null>
|
|
249
|
+
async getAdapterInstance(): Promise<any | null>
|
|
250
|
+
getAdapterMeta(): { type: string, opts?: any } | null
|
|
251
|
+
async pull(reference?: string, baseSnapshot?: Record<string, string>): Promise<any>
|
|
252
|
+
async push(input: CommitInput): Promise<any>
|
|
253
|
+
|
|
254
|
+
// Conflict Resolution
|
|
255
|
+
async getConflicts(): Promise<ConflictItem[]>
|
|
256
|
+
async resolveConflict(path: string, resolution: 'local' | 'remote'): Promise<void>
|
|
257
|
+
|
|
258
|
+
// Index Management
|
|
259
|
+
async getIndex(): Promise<IndexFile>
|
|
260
|
+
async saveIndex(): Promise<void>
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Stats-like object returned by `vfs.stat(path)` includes standard fields
|
|
264
|
+
// similar to Node.js `fs.Stats` and may include Git identifiers when available.
|
|
265
|
+
// Example Type (informational):
|
|
266
|
+
// interface FsStatsLike {
|
|
267
|
+
// dev: number; ino: number; mode: number; nlink: number; uid: number; gid: number;
|
|
268
|
+
// size: number; atime: Date; mtime: Date; ctime: Date; birthtime: Date;
|
|
269
|
+
// isFile(): boolean; isDirectory(): boolean;
|
|
270
|
+
// // Git-specific (optional):
|
|
271
|
+
// gitBlobSha?: string; // blob SHA for tracked file
|
|
272
|
+
// gitCommitSha?: string; // latest commit SHA touching this path
|
|
273
|
+
// gitRef?: string; // reference/branch used to derive these values
|
|
274
|
+
// }
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
#### Adapter Retrieval and Management
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
// Get persisted adapter metadata (configuration, not instance)
|
|
281
|
+
async getAdapter(): Promise<{ type: string, opts?: any } | null>
|
|
282
|
+
// Example:
|
|
283
|
+
const meta = await vfs.getAdapter()
|
|
284
|
+
if (meta) {
|
|
285
|
+
console.log('Adapter type:', meta.type)
|
|
286
|
+
console.log('Branch:', meta.opts?.branch)
|
|
287
|
+
console.log('Owner:', meta.opts?.owner) // GitHub case
|
|
288
|
+
}
|
|
67
289
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
290
|
+
// Get cached adapter metadata synchronously
|
|
291
|
+
getAdapterMeta(): { type: string, opts?: any } | null
|
|
292
|
+
// Example:
|
|
293
|
+
const meta = vfs.getAdapterMeta()
|
|
294
|
+
|
|
295
|
+
// Get or create adapter instance (lazy initialization)
|
|
296
|
+
async getAdapterInstance(): Promise<any | null>
|
|
297
|
+
// Example:
|
|
298
|
+
const adapter = await vfs.getAdapterInstance()
|
|
299
|
+
if (adapter) {
|
|
300
|
+
// adapter.resolveRef, adapter.push, etc. are now available
|
|
301
|
+
}
|
|
302
|
+
```
|
|
77
303
|
|
|
78
|
-
|
|
304
|
+
**Note**:
|
|
305
|
+
- `getAdapter()` and `getAdapterInstance()` serve different purposes
|
|
306
|
+
- `getAdapter()` returns persisted metadata (type and opts)
|
|
307
|
+
- `getAdapterInstance()` creates/retrieves the adapter instance from metadata
|
|
308
|
+
- `getAdapterMeta()` synchronously returns cached metadata (no Promise)
|
|
79
309
|
|
|
80
|
-
|
|
81
|
-
- OPFS availability depends on the browser; polyfills/mocks are used in tests.
|
|
310
|
+
### Storage Backends
|
|
82
311
|
|
|
83
|
-
|
|
312
|
+
```typescript
|
|
313
|
+
// OPFS Backend
|
|
314
|
+
class OpfsStorage implements StorageBackend {
|
|
315
|
+
constructor(namespace: string, rootName?: string)
|
|
316
|
+
}
|
|
84
317
|
|
|
85
|
-
|
|
318
|
+
// IndexedDB Backend
|
|
319
|
+
class IndexedDatabaseStorage implements StorageBackend {
|
|
320
|
+
constructor(namespace: string, rootName?: string)
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// In-Memory Backend (for testing)
|
|
324
|
+
class InMemoryStorage implements StorageBackend {
|
|
325
|
+
constructor(namespace: string, rootName?: string)
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Platform Adapters
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
// GitHub Adapter
|
|
333
|
+
class GitHubAdapter {
|
|
334
|
+
constructor(options: {
|
|
335
|
+
owner: string
|
|
336
|
+
repo: string
|
|
337
|
+
token: string
|
|
338
|
+
branch: string
|
|
339
|
+
})
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// GitLab Adapter
|
|
343
|
+
class GitLabAdapter {
|
|
344
|
+
constructor(options: {
|
|
345
|
+
projectId: string
|
|
346
|
+
host: string
|
|
347
|
+
token: string
|
|
348
|
+
branch: string
|
|
349
|
+
})
|
|
350
|
+
}
|
|
351
|
+
```
|
|
86
352
|
|
|
87
|
-
|
|
353
|
+
## Examples
|
|
88
354
|
|
|
89
|
-
|
|
90
|
-
-
|
|
91
|
-
-
|
|
92
|
-
-
|
|
93
|
-
- `applyBaseSnapshot(snapshot, headSha)` — apply remote snapshot, returns conflicts if any
|
|
355
|
+
See the [`examples/`](examples/) directory for:
|
|
356
|
+
- Interactive browser demo with UI
|
|
357
|
+
- Playwright E2E test scenarios
|
|
358
|
+
- Multiple storage backend examples
|
|
94
359
|
|
|
95
|
-
|
|
360
|
+
## Contributing
|
|
96
361
|
|
|
97
|
-
|
|
98
|
-
- `npm run test:e2e` requires a build (`npm run build`) before execution.
|
|
362
|
+
Contributions are welcome! Please follow these guidelines:
|
|
99
363
|
|
|
100
|
-
|
|
364
|
+
1. **Open an Issue**: For significant changes, please open an issue first to discuss your proposal
|
|
365
|
+
2. **Follow Conventions**:
|
|
366
|
+
- Use TypeScript
|
|
367
|
+
- Follow ESLint rules (`npm run lint`)
|
|
368
|
+
- Write tests for new features
|
|
369
|
+
- Update documentation as needed
|
|
370
|
+
3. **Testing**: Ensure all tests pass before submitting PR
|
|
371
|
+
```bash
|
|
372
|
+
npm run lint
|
|
373
|
+
npm run build
|
|
374
|
+
npm run test
|
|
375
|
+
npm run test:e2e
|
|
376
|
+
```
|
|
101
377
|
|
|
102
|
-
|
|
103
|
-
- Follow TypeScript + ESLint conventions; include tests for new behavior.
|
|
378
|
+
## Support
|
|
104
379
|
|
|
105
|
-
|
|
380
|
+
- **Issues**: https://github.com/nojaja/browser-git-ops/issues
|
|
381
|
+
- **Discussions**: https://github.com/nojaja/browser-git-ops/discussions
|
|
382
|
+
- **Documentation**: https://nojaja.github.io/browser-git-ops/
|
|
106
383
|
|
|
107
|
-
|
|
384
|
+
## License
|
|
108
385
|
|
|
109
|
-
License
|
|
386
|
+
MIT License - see the [LICENSE](LICENSE) file for details.
|
|
110
387
|
|
|
111
|
-
|
|
388
|
+
## Author
|
|
112
389
|
|
|
113
|
-
|
|
390
|
+
Maintained by [nojaja](https://github.com/nojaja) ([free.riccia@gmail.com](mailto:free.riccia@gmail.com))
|
|
114
391
|
|
|
115
|
-
|
|
392
|
+
## Acknowledgments
|
|
116
393
|
|
|
117
|
-
|
|
118
|
-
-
|
|
119
|
-
-
|
|
394
|
+
This project uses:
|
|
395
|
+
- OPFS (Origin Private File System) for persistent storage
|
|
396
|
+
- GitHub and GitLab Web APIs for remote synchronization
|
|
397
|
+
- Jest for unit testing
|
|
398
|
+
- Playwright for E2E testing
|
|
@@ -58,6 +58,14 @@ export declare class RetryableError extends Error {
|
|
|
58
58
|
*/
|
|
59
59
|
export declare class NonRetryableError extends Error {
|
|
60
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Error indicating that retry attempts were exhausted and no further retries will be made.
|
|
63
|
+
*/
|
|
64
|
+
export declare class RetryExhaustedError extends RetryableError {
|
|
65
|
+
code: string;
|
|
66
|
+
cause?: any;
|
|
67
|
+
constructor(message: string, cause?: any);
|
|
68
|
+
}
|
|
61
69
|
/**
|
|
62
70
|
* Map items with limited concurrency
|
|
63
71
|
* @template T,R
|
|
@@ -66,7 +74,14 @@ export declare class NonRetryableError extends Error {
|
|
|
66
74
|
* @param concurrency concurrency limit
|
|
67
75
|
* @returns Promise resolving to array of mapped results
|
|
68
76
|
*/
|
|
69
|
-
export
|
|
77
|
+
export type MapWithConcurrencyOptions = {
|
|
78
|
+
controller?: AbortController;
|
|
79
|
+
};
|
|
80
|
+
export declare function processOne<T, R>(items: T[], mapper: (_t: T) => Promise<R>, results: R[], index_: number, controller?: AbortController): Promise<void>;
|
|
81
|
+
export declare function queueRunWorker<T, R>(items: T[], mapper: (_t: T) => Promise<R>, results: R[], indexReference: {
|
|
82
|
+
value: number;
|
|
83
|
+
}, controller?: AbortController): Promise<void>;
|
|
84
|
+
export declare function mapWithConcurrency<T, R>(items: T[], mapper: (_t: T) => Promise<R>, concurrency?: number, options?: MapWithConcurrencyOptions): Promise<R[]>;
|
|
70
85
|
/**
|
|
71
86
|
* Abstract base class providing shared utilities for Git adapters
|
|
72
87
|
*/
|
|
@@ -102,27 +117,19 @@ export declare abstract class AbstractGitAdapter {
|
|
|
102
117
|
protected logDebug(..._messages: any[]): void;
|
|
103
118
|
/**
|
|
104
119
|
* Log an informational message if a logger is present.
|
|
105
|
-
* @param
|
|
120
|
+
* @param _messages items to log
|
|
106
121
|
*/
|
|
107
122
|
protected logInfo(..._messages: any[]): void;
|
|
108
123
|
/**
|
|
109
124
|
* Log a warning message if a logger is present.
|
|
110
|
-
* @param
|
|
125
|
+
* @param _messages items to log
|
|
111
126
|
*/
|
|
112
127
|
protected logWarn(..._messages: any[]): void;
|
|
113
128
|
/**
|
|
114
129
|
* Log an error message if a logger is present.
|
|
115
|
-
* @param
|
|
130
|
+
* @param _messages items to log
|
|
116
131
|
*/
|
|
117
132
|
protected logError(..._messages: any[]): void;
|
|
118
|
-
/**
|
|
119
|
-
* Proxy to shared fetchWithRetry implementation
|
|
120
|
-
* @param input RequestInfo
|
|
121
|
-
* @param init RequestInit
|
|
122
|
-
* @param attempts retry attempts
|
|
123
|
-
* @param baseDelay base delay ms
|
|
124
|
-
* @returns Promise resolving to Response
|
|
125
|
-
*/
|
|
126
133
|
/**
|
|
127
134
|
* Normalize different header-like shapes into a plain object.
|
|
128
135
|
* @param headerLike headers in Headers, array, or plain object form
|
|
@@ -131,11 +138,16 @@ export declare abstract class AbstractGitAdapter {
|
|
|
131
138
|
private normalizeHeaders;
|
|
132
139
|
/**
|
|
133
140
|
* Format a fetch request into a minimal object suitable for logging.
|
|
141
|
+
* @param input fetch input (URL or Request)
|
|
142
|
+
* @param init fetch initialization options
|
|
143
|
+
* @param attempts retry attempts count
|
|
144
|
+
* @param baseDelay base delay in milliseconds
|
|
134
145
|
* @returns formatted request log object
|
|
135
146
|
*/
|
|
136
147
|
private formatRequestForLog;
|
|
137
148
|
/**
|
|
138
149
|
* Format a fetch Response into a minimal object suitable for logging.
|
|
150
|
+
* @param response HTTP response object
|
|
139
151
|
* @returns formatted response log object
|
|
140
152
|
*/
|
|
141
153
|
private formatResponseForLog;
|
|
@@ -161,14 +173,6 @@ export declare abstract class AbstractGitAdapter {
|
|
|
161
173
|
* @returns milliseconds to wait
|
|
162
174
|
*/
|
|
163
175
|
protected backoffMs(attempt: number): number;
|
|
164
|
-
/**
|
|
165
|
-
* Delegate to shared mapWithConcurrency implementation
|
|
166
|
-
* @template T,R
|
|
167
|
-
* @param items items to map
|
|
168
|
-
* @param mapper async mapper
|
|
169
|
-
* @param concurrency concurrency limit
|
|
170
|
-
* @returns Promise resolving to mapped results
|
|
171
|
-
*/
|
|
172
176
|
/**
|
|
173
177
|
* Map items with limited concurrency by delegating to the shared helper.
|
|
174
178
|
* @template T,R
|
|
@@ -177,7 +181,7 @@ export declare abstract class AbstractGitAdapter {
|
|
|
177
181
|
* @param concurrency concurrency limit
|
|
178
182
|
* @returns Promise resolving to mapped results
|
|
179
183
|
*/
|
|
180
|
-
protected mapWithConcurrency<T, R>(items: T[], mapper: (_t: T) => Promise<R>, concurrency?: number): Promise<R[]>;
|
|
184
|
+
protected mapWithConcurrency<T, R>(items: T[], mapper: (_t: T) => Promise<R>, concurrency?: number, options?: MapWithConcurrencyOptions): Promise<R[]>;
|
|
181
185
|
}
|
|
182
186
|
export default AbstractGitAdapter;
|
|
183
187
|
//# sourceMappingURL=abstractAdapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abstractAdapter.d.ts","sourceRoot":"","sources":["../../src/git/abstractAdapter.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,sBAAsB,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAK5I;;;;;GAKG;AACH,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,CAAC,GAAG,SAAS,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;IACpC,IAAI,EAAE,CAAC,GAAG,SAAS,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;IACnC,IAAI,EAAE,CAAC,GAAG,SAAS,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;IACnC,KAAK,EAAE,CAAC,GAAG,SAAS,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;CACrC;
|
|
1
|
+
{"version":3,"file":"abstractAdapter.d.ts","sourceRoot":"","sources":["../../src/git/abstractAdapter.ts"],"names":[],"mappings":"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"}
|