git-daemon 0.1.0

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/openapi.yaml ADDED
@@ -0,0 +1,678 @@
1
+ openapi: 3.0.3
2
+ info:
3
+ title: Git Daemon API
4
+ version: 0.1.0
5
+ description: |
6
+ Localhost API for the Git Daemon. All requests must include an Origin header
7
+ that matches the allowlist. Non-public endpoints require a Bearer token.
8
+ servers:
9
+ - url: http://127.0.0.1:8787
10
+ security:
11
+ - bearerAuth: []
12
+ paths:
13
+ /v1/meta:
14
+ get:
15
+ summary: Get daemon status and capabilities
16
+ security: []
17
+ parameters:
18
+ - $ref: '#/components/parameters/OriginHeader'
19
+ responses:
20
+ '200':
21
+ description: Daemon status and capabilities
22
+ content:
23
+ application/json:
24
+ schema:
25
+ $ref: '#/components/schemas/MetaResponse'
26
+ '403':
27
+ $ref: '#/components/responses/Forbidden'
28
+ '500':
29
+ $ref: '#/components/responses/InternalError'
30
+ /v1/pair:
31
+ post:
32
+ summary: Start or confirm pairing
33
+ security: []
34
+ parameters:
35
+ - $ref: '#/components/parameters/OriginHeader'
36
+ requestBody:
37
+ required: true
38
+ content:
39
+ application/json:
40
+ schema:
41
+ $ref: '#/components/schemas/PairRequest'
42
+ responses:
43
+ '200':
44
+ description: Pairing response
45
+ content:
46
+ application/json:
47
+ schema:
48
+ $ref: '#/components/schemas/PairResponse'
49
+ '403':
50
+ $ref: '#/components/responses/Forbidden'
51
+ '422':
52
+ $ref: '#/components/responses/UnprocessableEntity'
53
+ '429':
54
+ $ref: '#/components/responses/RateLimited'
55
+ '500':
56
+ $ref: '#/components/responses/InternalError'
57
+ /v1/jobs/{id}:
58
+ get:
59
+ summary: Get job status
60
+ parameters:
61
+ - $ref: '#/components/parameters/OriginHeader'
62
+ - $ref: '#/components/parameters/JobId'
63
+ responses:
64
+ '200':
65
+ description: Job status
66
+ content:
67
+ application/json:
68
+ schema:
69
+ $ref: '#/components/schemas/JobStatus'
70
+ '401':
71
+ $ref: '#/components/responses/Unauthorized'
72
+ '403':
73
+ $ref: '#/components/responses/Forbidden'
74
+ '404':
75
+ $ref: '#/components/responses/NotFound'
76
+ '500':
77
+ $ref: '#/components/responses/InternalError'
78
+ /v1/jobs/{id}/stream:
79
+ get:
80
+ summary: Stream job logs and events (SSE)
81
+ parameters:
82
+ - $ref: '#/components/parameters/OriginHeader'
83
+ - $ref: '#/components/parameters/JobId'
84
+ responses:
85
+ '200':
86
+ description: Server-sent events stream
87
+ content:
88
+ text/event-stream:
89
+ schema:
90
+ type: string
91
+ example: |
92
+ data: {"type":"log","stream":"stdout","line":"Cloning into..."}
93
+
94
+ data: {"type":"progress","kind":"git","percent":42,"detail":"receiving objects"}
95
+ '401':
96
+ $ref: '#/components/responses/Unauthorized'
97
+ '403':
98
+ $ref: '#/components/responses/Forbidden'
99
+ '404':
100
+ $ref: '#/components/responses/NotFound'
101
+ '500':
102
+ $ref: '#/components/responses/InternalError'
103
+ /v1/jobs/{id}/cancel:
104
+ post:
105
+ summary: Request job cancellation
106
+ parameters:
107
+ - $ref: '#/components/parameters/OriginHeader'
108
+ - $ref: '#/components/parameters/JobId'
109
+ responses:
110
+ '200':
111
+ description: Cancellation accepted
112
+ content:
113
+ application/json:
114
+ schema:
115
+ $ref: '#/components/schemas/CancelResponse'
116
+ '401':
117
+ $ref: '#/components/responses/Unauthorized'
118
+ '403':
119
+ $ref: '#/components/responses/Forbidden'
120
+ '404':
121
+ $ref: '#/components/responses/NotFound'
122
+ '409':
123
+ $ref: '#/components/responses/Conflict'
124
+ '500':
125
+ $ref: '#/components/responses/InternalError'
126
+ /v1/git/clone:
127
+ post:
128
+ summary: Clone a repository
129
+ parameters:
130
+ - $ref: '#/components/parameters/OriginHeader'
131
+ requestBody:
132
+ required: true
133
+ content:
134
+ application/json:
135
+ schema:
136
+ $ref: '#/components/schemas/GitCloneRequest'
137
+ responses:
138
+ '202':
139
+ description: Job created
140
+ content:
141
+ application/json:
142
+ schema:
143
+ $ref: '#/components/schemas/JobResponse'
144
+ '401':
145
+ $ref: '#/components/responses/Unauthorized'
146
+ '403':
147
+ $ref: '#/components/responses/Forbidden'
148
+ '409':
149
+ $ref: '#/components/responses/Conflict'
150
+ '422':
151
+ $ref: '#/components/responses/UnprocessableEntity'
152
+ '500':
153
+ $ref: '#/components/responses/InternalError'
154
+ /v1/git/fetch:
155
+ post:
156
+ summary: Fetch from a remote without pulling
157
+ parameters:
158
+ - $ref: '#/components/parameters/OriginHeader'
159
+ requestBody:
160
+ required: true
161
+ content:
162
+ application/json:
163
+ schema:
164
+ $ref: '#/components/schemas/GitFetchRequest'
165
+ responses:
166
+ '202':
167
+ description: Job created
168
+ content:
169
+ application/json:
170
+ schema:
171
+ $ref: '#/components/schemas/JobResponse'
172
+ '401':
173
+ $ref: '#/components/responses/Unauthorized'
174
+ '403':
175
+ $ref: '#/components/responses/Forbidden'
176
+ '404':
177
+ $ref: '#/components/responses/NotFound'
178
+ '409':
179
+ $ref: '#/components/responses/Conflict'
180
+ '422':
181
+ $ref: '#/components/responses/UnprocessableEntity'
182
+ '500':
183
+ $ref: '#/components/responses/InternalError'
184
+ /v1/git/status:
185
+ get:
186
+ summary: Get repository status
187
+ parameters:
188
+ - $ref: '#/components/parameters/OriginHeader'
189
+ - $ref: '#/components/parameters/RepoPath'
190
+ responses:
191
+ '200':
192
+ description: Repository status
193
+ content:
194
+ application/json:
195
+ schema:
196
+ $ref: '#/components/schemas/GitStatus'
197
+ '401':
198
+ $ref: '#/components/responses/Unauthorized'
199
+ '403':
200
+ $ref: '#/components/responses/Forbidden'
201
+ '404':
202
+ $ref: '#/components/responses/NotFound'
203
+ '409':
204
+ $ref: '#/components/responses/Conflict'
205
+ '422':
206
+ $ref: '#/components/responses/UnprocessableEntity'
207
+ '500':
208
+ $ref: '#/components/responses/InternalError'
209
+ /v1/os/open:
210
+ post:
211
+ summary: Open a folder, terminal, or VS Code
212
+ parameters:
213
+ - $ref: '#/components/parameters/OriginHeader'
214
+ requestBody:
215
+ required: true
216
+ content:
217
+ application/json:
218
+ schema:
219
+ $ref: '#/components/schemas/OsOpenRequest'
220
+ responses:
221
+ '200':
222
+ description: Open action accepted
223
+ content:
224
+ application/json:
225
+ schema:
226
+ $ref: '#/components/schemas/OkResponse'
227
+ '401':
228
+ $ref: '#/components/responses/Unauthorized'
229
+ '403':
230
+ $ref: '#/components/responses/Forbidden'
231
+ '409':
232
+ $ref: '#/components/responses/Conflict'
233
+ '422':
234
+ $ref: '#/components/responses/UnprocessableEntity'
235
+ '500':
236
+ $ref: '#/components/responses/InternalError'
237
+ /v1/deps/install:
238
+ post:
239
+ summary: Install dependencies
240
+ parameters:
241
+ - $ref: '#/components/parameters/OriginHeader'
242
+ requestBody:
243
+ required: true
244
+ content:
245
+ application/json:
246
+ schema:
247
+ $ref: '#/components/schemas/DepsInstallRequest'
248
+ responses:
249
+ '202':
250
+ description: Job created
251
+ content:
252
+ application/json:
253
+ schema:
254
+ $ref: '#/components/schemas/JobResponse'
255
+ '401':
256
+ $ref: '#/components/responses/Unauthorized'
257
+ '403':
258
+ $ref: '#/components/responses/Forbidden'
259
+ '404':
260
+ $ref: '#/components/responses/NotFound'
261
+ '409':
262
+ $ref: '#/components/responses/Conflict'
263
+ '422':
264
+ $ref: '#/components/responses/UnprocessableEntity'
265
+ '500':
266
+ $ref: '#/components/responses/InternalError'
267
+ /v1/diagnostics:
268
+ get:
269
+ summary: Get diagnostics bundle metadata
270
+ parameters:
271
+ - $ref: '#/components/parameters/OriginHeader'
272
+ responses:
273
+ '200':
274
+ description: Diagnostics data
275
+ content:
276
+ application/json:
277
+ schema:
278
+ $ref: '#/components/schemas/DiagnosticsResponse'
279
+ '401':
280
+ $ref: '#/components/responses/Unauthorized'
281
+ '403':
282
+ $ref: '#/components/responses/Forbidden'
283
+ '500':
284
+ $ref: '#/components/responses/InternalError'
285
+ components:
286
+ securitySchemes:
287
+ bearerAuth:
288
+ type: http
289
+ scheme: bearer
290
+ bearerFormat: token
291
+ parameters:
292
+ OriginHeader:
293
+ name: Origin
294
+ in: header
295
+ required: true
296
+ schema:
297
+ type: string
298
+ description: Must match the configured origin allowlist.
299
+ JobId:
300
+ name: id
301
+ in: path
302
+ required: true
303
+ schema:
304
+ type: string
305
+ RepoPath:
306
+ name: repoPath
307
+ in: query
308
+ required: true
309
+ schema:
310
+ type: string
311
+ schemas:
312
+ MetaResponse:
313
+ type: object
314
+ required:
315
+ - version
316
+ - pairing
317
+ - workspace
318
+ - capabilities
319
+ properties:
320
+ version:
321
+ type: string
322
+ build:
323
+ type: object
324
+ properties:
325
+ commit:
326
+ type: string
327
+ date:
328
+ type: string
329
+ format: date-time
330
+ pairing:
331
+ $ref: '#/components/schemas/PairingState'
332
+ workspace:
333
+ $ref: '#/components/schemas/WorkspaceState'
334
+ capabilities:
335
+ $ref: '#/components/schemas/Capabilities'
336
+ PairingState:
337
+ type: object
338
+ required:
339
+ - required
340
+ - paired
341
+ properties:
342
+ required:
343
+ type: boolean
344
+ paired:
345
+ type: boolean
346
+ WorkspaceState:
347
+ type: object
348
+ required:
349
+ - configured
350
+ properties:
351
+ configured:
352
+ type: boolean
353
+ root:
354
+ type: string
355
+ Capabilities:
356
+ type: object
357
+ required:
358
+ - tools
359
+ properties:
360
+ tools:
361
+ type: object
362
+ properties:
363
+ git:
364
+ $ref: '#/components/schemas/ToolInfo'
365
+ node:
366
+ $ref: '#/components/schemas/ToolInfo'
367
+ npm:
368
+ $ref: '#/components/schemas/ToolInfo'
369
+ pnpm:
370
+ $ref: '#/components/schemas/ToolInfo'
371
+ yarn:
372
+ $ref: '#/components/schemas/ToolInfo'
373
+ code:
374
+ $ref: '#/components/schemas/ToolInfo'
375
+ ToolInfo:
376
+ type: object
377
+ required:
378
+ - installed
379
+ properties:
380
+ installed:
381
+ type: boolean
382
+ version:
383
+ type: string
384
+ PairRequest:
385
+ oneOf:
386
+ - $ref: '#/components/schemas/PairStartRequest'
387
+ - $ref: '#/components/schemas/PairConfirmRequest'
388
+ discriminator:
389
+ propertyName: step
390
+ mapping:
391
+ start: '#/components/schemas/PairStartRequest'
392
+ confirm: '#/components/schemas/PairConfirmRequest'
393
+ PairStartRequest:
394
+ type: object
395
+ required:
396
+ - step
397
+ properties:
398
+ step:
399
+ type: string
400
+ enum: [start]
401
+ PairConfirmRequest:
402
+ type: object
403
+ required:
404
+ - step
405
+ - code
406
+ properties:
407
+ step:
408
+ type: string
409
+ enum: [confirm]
410
+ code:
411
+ type: string
412
+ PairResponse:
413
+ oneOf:
414
+ - $ref: '#/components/schemas/PairStartResponse'
415
+ - $ref: '#/components/schemas/PairConfirmResponse'
416
+ discriminator:
417
+ propertyName: step
418
+ mapping:
419
+ start: '#/components/schemas/PairStartResponse'
420
+ confirm: '#/components/schemas/PairConfirmResponse'
421
+ PairStartResponse:
422
+ type: object
423
+ required:
424
+ - step
425
+ - instructions
426
+ properties:
427
+ step:
428
+ type: string
429
+ enum: [start]
430
+ instructions:
431
+ type: string
432
+ code:
433
+ type: string
434
+ expiresAt:
435
+ type: string
436
+ format: date-time
437
+ PairConfirmResponse:
438
+ type: object
439
+ required:
440
+ - step
441
+ - accessToken
442
+ - tokenType
443
+ - expiresAt
444
+ properties:
445
+ step:
446
+ type: string
447
+ enum: [confirm]
448
+ accessToken:
449
+ type: string
450
+ tokenType:
451
+ type: string
452
+ enum: [Bearer]
453
+ expiresAt:
454
+ type: string
455
+ format: date-time
456
+ JobResponse:
457
+ type: object
458
+ required:
459
+ - jobId
460
+ properties:
461
+ jobId:
462
+ type: string
463
+ JobStatus:
464
+ type: object
465
+ required:
466
+ - id
467
+ - state
468
+ properties:
469
+ id:
470
+ type: string
471
+ state:
472
+ type: string
473
+ enum: [queued, running, done, error, cancelled]
474
+ createdAt:
475
+ type: string
476
+ format: date-time
477
+ startedAt:
478
+ type: string
479
+ format: date-time
480
+ finishedAt:
481
+ type: string
482
+ format: date-time
483
+ error:
484
+ $ref: '#/components/schemas/ErrorResponse'
485
+ GitCloneRequest:
486
+ type: object
487
+ required:
488
+ - repoUrl
489
+ - destRelative
490
+ properties:
491
+ repoUrl:
492
+ type: string
493
+ destRelative:
494
+ type: string
495
+ options:
496
+ type: object
497
+ properties:
498
+ branch:
499
+ type: string
500
+ depth:
501
+ type: integer
502
+ minimum: 1
503
+ GitFetchRequest:
504
+ type: object
505
+ required:
506
+ - repoPath
507
+ properties:
508
+ repoPath:
509
+ type: string
510
+ remote:
511
+ type: string
512
+ default: origin
513
+ prune:
514
+ type: boolean
515
+ default: false
516
+ GitStatus:
517
+ type: object
518
+ required:
519
+ - branch
520
+ - ahead
521
+ - behind
522
+ - stagedCount
523
+ - unstagedCount
524
+ - untrackedCount
525
+ - conflictsCount
526
+ - clean
527
+ properties:
528
+ branch:
529
+ type: string
530
+ ahead:
531
+ type: integer
532
+ minimum: 0
533
+ behind:
534
+ type: integer
535
+ minimum: 0
536
+ stagedCount:
537
+ type: integer
538
+ minimum: 0
539
+ unstagedCount:
540
+ type: integer
541
+ minimum: 0
542
+ untrackedCount:
543
+ type: integer
544
+ minimum: 0
545
+ conflictsCount:
546
+ type: integer
547
+ minimum: 0
548
+ clean:
549
+ type: boolean
550
+ OsOpenRequest:
551
+ type: object
552
+ required:
553
+ - target
554
+ - path
555
+ properties:
556
+ target:
557
+ type: string
558
+ enum: [folder, terminal, vscode]
559
+ path:
560
+ type: string
561
+ DepsInstallRequest:
562
+ type: object
563
+ required:
564
+ - repoPath
565
+ properties:
566
+ repoPath:
567
+ type: string
568
+ manager:
569
+ type: string
570
+ enum: [auto, npm, pnpm, yarn]
571
+ default: auto
572
+ mode:
573
+ type: string
574
+ enum: [auto, ci, install]
575
+ default: auto
576
+ safer:
577
+ type: boolean
578
+ default: true
579
+ CancelResponse:
580
+ type: object
581
+ required:
582
+ - accepted
583
+ properties:
584
+ accepted:
585
+ type: boolean
586
+ OkResponse:
587
+ type: object
588
+ required:
589
+ - ok
590
+ properties:
591
+ ok:
592
+ type: boolean
593
+ DiagnosticsResponse:
594
+ type: object
595
+ properties:
596
+ config:
597
+ type: object
598
+ description: Redacted config summary
599
+ recentErrors:
600
+ type: array
601
+ items:
602
+ type: object
603
+ jobs:
604
+ type: array
605
+ items:
606
+ $ref: '#/components/schemas/JobStatus'
607
+ logTail:
608
+ type: array
609
+ items:
610
+ type: string
611
+ ErrorResponse:
612
+ type: object
613
+ required:
614
+ - errorCode
615
+ - message
616
+ properties:
617
+ errorCode:
618
+ type: string
619
+ enum:
620
+ - auth_required
621
+ - auth_invalid
622
+ - origin_not_allowed
623
+ - rate_limited
624
+ - request_too_large
625
+ - workspace_required
626
+ - path_outside_workspace
627
+ - invalid_repo_url
628
+ - capability_not_granted
629
+ - job_not_found
630
+ - timeout
631
+ - internal_error
632
+ message:
633
+ type: string
634
+ details:
635
+ type: object
636
+ responses:
637
+ Unauthorized:
638
+ description: Missing or invalid bearer token
639
+ content:
640
+ application/json:
641
+ schema:
642
+ $ref: '#/components/schemas/ErrorResponse'
643
+ Forbidden:
644
+ description: Origin not allowed or request denied
645
+ content:
646
+ application/json:
647
+ schema:
648
+ $ref: '#/components/schemas/ErrorResponse'
649
+ NotFound:
650
+ description: Resource not found
651
+ content:
652
+ application/json:
653
+ schema:
654
+ $ref: '#/components/schemas/ErrorResponse'
655
+ Conflict:
656
+ description: Operation not allowed
657
+ content:
658
+ application/json:
659
+ schema:
660
+ $ref: '#/components/schemas/ErrorResponse'
661
+ UnprocessableEntity:
662
+ description: Invalid input
663
+ content:
664
+ application/json:
665
+ schema:
666
+ $ref: '#/components/schemas/ErrorResponse'
667
+ RateLimited:
668
+ description: Rate limited
669
+ content:
670
+ application/json:
671
+ schema:
672
+ $ref: '#/components/schemas/ErrorResponse'
673
+ InternalError:
674
+ description: Unexpected failure
675
+ content:
676
+ application/json:
677
+ schema:
678
+ $ref: '#/components/schemas/ErrorResponse'
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "git-daemon",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "type": "commonjs",
6
+ "main": "dist/daemon.js",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "daemon": "tsx src/daemon.ts",
10
+ "test": "vitest run",
11
+ "test:watch": "vitest",
12
+ "lint": "eslint . --ext .ts",
13
+ "lint:fix": "eslint . --ext .ts --fix"
14
+ },
15
+ "dependencies": {
16
+ "env-paths": "^3.0.0",
17
+ "execa": "^8.0.1",
18
+ "express": "^4.19.2",
19
+ "express-rate-limit": "^7.4.0",
20
+ "pino": "^9.3.2",
21
+ "pino-http": "^9.0.0",
22
+ "rotating-file-stream": "^3.2.5",
23
+ "tree-kill": "^1.2.2",
24
+ "zod": "^3.23.8"
25
+ },
26
+ "devDependencies": {
27
+ "@types/express": "^4.17.21",
28
+ "@types/node": "^20.14.9",
29
+ "@types/supertest": "^2.0.16",
30
+ "supertest": "^7.0.0",
31
+ "@typescript-eslint/eslint-plugin": "^7.16.1",
32
+ "@typescript-eslint/parser": "^7.16.1",
33
+ "eslint": "^8.57.0",
34
+ "eslint-config-prettier": "^9.1.0",
35
+ "eslint-plugin-prettier": "^5.2.1",
36
+ "prettier": "^3.3.3",
37
+ "tsx": "^4.19.2",
38
+ "typescript": "^5.5.3",
39
+ "vitest": "^2.0.5"
40
+ }
41
+ }