@contextgit/api 0.0.3

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.
Files changed (41) hide show
  1. package/dist/bootstrap.d.ts +10 -0
  2. package/dist/bootstrap.d.ts.map +1 -0
  3. package/dist/bootstrap.js +40 -0
  4. package/dist/bootstrap.js.map +1 -0
  5. package/dist/config.d.ts +7 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +40 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/index.d.ts +2 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +15 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/middleware/auth.d.ts +3 -0
  14. package/dist/middleware/auth.d.ts.map +1 -0
  15. package/dist/middleware/auth.js +32 -0
  16. package/dist/middleware/auth.js.map +1 -0
  17. package/dist/middleware/auth.test.d.ts +2 -0
  18. package/dist/middleware/auth.test.d.ts.map +1 -0
  19. package/dist/middleware/auth.test.js +77 -0
  20. package/dist/middleware/auth.test.js.map +1 -0
  21. package/dist/remote-store.test.d.ts +2 -0
  22. package/dist/remote-store.test.d.ts.map +1 -0
  23. package/dist/remote-store.test.js +256 -0
  24. package/dist/remote-store.test.js.map +1 -0
  25. package/dist/router.d.ts +4 -0
  26. package/dist/router.d.ts.map +1 -0
  27. package/dist/router.js +103 -0
  28. package/dist/router.js.map +1 -0
  29. package/dist/server-config.d.ts +7 -0
  30. package/dist/server-config.d.ts.map +1 -0
  31. package/dist/server-config.js +27 -0
  32. package/dist/server-config.js.map +1 -0
  33. package/dist/server.d.ts +3 -0
  34. package/dist/server.d.ts.map +1 -0
  35. package/dist/server.js +32 -0
  36. package/dist/server.js.map +1 -0
  37. package/dist/store-router.d.ts +4 -0
  38. package/dist/store-router.d.ts.map +1 -0
  39. package/dist/store-router.js +281 -0
  40. package/dist/store-router.js.map +1 -0
  41. package/package.json +26 -0
@@ -0,0 +1,10 @@
1
+ import { ContextEngine } from '@contextgit/core';
2
+ import type { ContextStore } from '@contextgit/store';
3
+ export interface ApiContext {
4
+ engine: ContextEngine;
5
+ store: ContextStore;
6
+ projectId: string;
7
+ branchId: string;
8
+ }
9
+ export declare function bootstrap(): Promise<ApiContext>;
10
+ //# sourceMappingURL=bootstrap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAEhD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGrD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,aAAa,CAAA;IACrB,KAAK,EAAE,YAAY,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;CACjB;AA4BD,wBAAsB,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC,CAqBrD"}
@@ -0,0 +1,40 @@
1
+ // bootstrap.ts — shared setup: load config, open store, detect git branch, init engine.
2
+ import os from 'os';
3
+ import { simpleGit } from 'simple-git';
4
+ import { ContextEngine } from '@contextgit/core';
5
+ import { LocalStore } from '@contextgit/store';
6
+ import { loadConfig } from './config.js';
7
+ async function detectGitBranch() {
8
+ try {
9
+ const git = simpleGit(process.cwd());
10
+ const result = await git.revparse(['--abbrev-ref', 'HEAD']);
11
+ return result.trim();
12
+ }
13
+ catch {
14
+ return 'main';
15
+ }
16
+ }
17
+ async function resolveContextBranch(store, projectId, gitBranch) {
18
+ const existing = await store.getBranchByGitName(projectId, gitBranch);
19
+ if (existing)
20
+ return existing.id;
21
+ const created = await store.createBranch({
22
+ projectId,
23
+ name: `Context: ${gitBranch}`,
24
+ gitBranch,
25
+ });
26
+ return created.id;
27
+ }
28
+ export async function bootstrap() {
29
+ const config = loadConfig();
30
+ const { projectId } = config;
31
+ const store = new LocalStore(projectId);
32
+ const gitBranch = await detectGitBranch();
33
+ const branchId = await resolveContextBranch(store, projectId, gitBranch);
34
+ const hostname = os.hostname();
35
+ const agentId = `${hostname}-api-server`;
36
+ const engine = new ContextEngine(store, agentId, config.agentRole ?? 'solo', 'contextgit-api', config.workflowType ?? 'interactive');
37
+ await engine.init(projectId, branchId);
38
+ return { engine, store, projectId, branchId };
39
+ }
40
+ //# sourceMappingURL=bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAAA,wFAAwF;AAExF,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AASxC,KAAK,UAAU,eAAe;IAC5B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;QACpC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAA;QAC3D,OAAO,MAAM,CAAC,IAAI,EAAE,CAAA;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAA;IACf,CAAC;AACH,CAAC;AAED,KAAK,UAAU,oBAAoB,CACjC,KAAmB,EACnB,SAAiB,EACjB,SAAiB;IAEjB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,kBAAkB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;IACrE,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC,EAAE,CAAA;IAEhC,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,YAAY,CAAC;QACvC,SAAS;QACT,IAAI,EAAE,YAAY,SAAS,EAAE;QAC7B,SAAS;KACV,CAAC,CAAA;IACF,OAAO,OAAO,CAAC,EAAE,CAAA;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;IAC3B,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAAA;IAE5B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,CAAA;IACvC,MAAM,SAAS,GAAG,MAAM,eAAe,EAAE,CAAA;IACzC,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,CAAA;IAExE,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAA;IAC9B,MAAM,OAAO,GAAG,GAAG,QAAQ,aAAa,CAAA;IAExC,MAAM,MAAM,GAAG,IAAI,aAAa,CAC9B,KAAK,EACL,OAAO,EACP,MAAM,CAAC,SAAS,IAAI,MAAM,EAC1B,gBAAgB,EAChB,MAAM,CAAC,YAAY,IAAI,aAAa,CACrC,CAAA;IACD,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IAEtC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAA;AAC/C,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { ContextGitConfig } from '@contextgit/core';
2
+ export declare class ConfigNotFoundError extends Error {
3
+ constructor(startDir: string);
4
+ }
5
+ export declare function findConfigPath(startDir?: string): string;
6
+ export declare function loadConfig(startDir?: string): ContextGitConfig;
7
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAExD,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,QAAQ,EAAE,MAAM;CAI7B;AAED,wBAAgB,cAAc,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,CAevE;AAED,wBAAgB,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAa9D"}
package/dist/config.js ADDED
@@ -0,0 +1,40 @@
1
+ // config.ts — load and validate .contextgit/config.json
2
+ // Searches from CWD upwards until it finds the config file.
3
+ import { readFileSync } from 'fs';
4
+ import { join, dirname } from 'path';
5
+ export class ConfigNotFoundError extends Error {
6
+ constructor(startDir) {
7
+ super(`No .contextgit/config.json found searching upward from: ${startDir}`);
8
+ this.name = 'ConfigNotFoundError';
9
+ }
10
+ }
11
+ export function findConfigPath(startDir = process.cwd()) {
12
+ let current = startDir;
13
+ while (true) {
14
+ const candidate = join(current, '.contextgit', 'config.json');
15
+ try {
16
+ readFileSync(candidate);
17
+ return candidate;
18
+ }
19
+ catch {
20
+ const parent = dirname(current);
21
+ if (parent === current) {
22
+ throw new ConfigNotFoundError(startDir);
23
+ }
24
+ current = parent;
25
+ }
26
+ }
27
+ }
28
+ export function loadConfig(startDir) {
29
+ const configPath = findConfigPath(startDir);
30
+ const raw = readFileSync(configPath, 'utf-8');
31
+ const config = JSON.parse(raw);
32
+ if (!config.projectId) {
33
+ throw new Error(`Invalid config at ${configPath}: missing required field 'projectId'`);
34
+ }
35
+ if (!config.project) {
36
+ throw new Error(`Invalid config at ${configPath}: missing required field 'project'`);
37
+ }
38
+ return config;
39
+ }
40
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,4DAA4D;AAE5D,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAGpC,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,QAAgB;QAC1B,KAAK,CAAC,2DAA2D,QAAQ,EAAE,CAAC,CAAA;QAC5E,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAA;IACnC,CAAC;CACF;AAED,MAAM,UAAU,cAAc,CAAC,WAAmB,OAAO,CAAC,GAAG,EAAE;IAC7D,IAAI,OAAO,GAAG,QAAQ,CAAA;IACtB,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,aAAa,EAAE,aAAa,CAAC,CAAA;QAC7D,IAAI,CAAC;YACH,YAAY,CAAC,SAAS,CAAC,CAAA;YACvB,OAAO,SAAS,CAAA;QAClB,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;YAC/B,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;gBACvB,MAAM,IAAI,mBAAmB,CAAC,QAAQ,CAAC,CAAA;YACzC,CAAC;YACD,OAAO,GAAG,MAAM,CAAA;QAClB,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAAiB;IAC1C,MAAM,UAAU,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAA;IAC3C,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAqB,CAAA;IAElD,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,qBAAqB,UAAU,sCAAsC,CAAC,CAAA;IACxF,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,qBAAqB,UAAU,oCAAoC,CAAC,CAAA;IACtF,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ // index.ts — ContextGit REST API entry point
2
+ // Starts the Express server on PORT (default 3141).
3
+ import { createApp } from './server.js';
4
+ const PORT = parseInt(process.env['PORT'] ?? '3141', 10);
5
+ createApp()
6
+ .then(app => {
7
+ app.listen(PORT, () => {
8
+ console.log(`ContextGit API listening on http://localhost:${PORT}`);
9
+ });
10
+ })
11
+ .catch(err => {
12
+ console.error('Failed to start ContextGit API:', err);
13
+ process.exit(1);
14
+ });
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,oDAAoD;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEvC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,MAAM,EAAE,EAAE,CAAC,CAAA;AAExD,SAAS,EAAE;KACR,IAAI,CAAC,GAAG,CAAC,EAAE;IACV,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;QACpB,OAAO,CAAC,GAAG,CAAC,gDAAgD,IAAI,EAAE,CAAC,CAAA;IACrE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC;KACD,KAAK,CAAC,GAAG,CAAC,EAAE;IACX,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,GAAG,CAAC,CAAA;IACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { Request, Response, NextFunction } from 'express';
2
+ export declare function createAuthMiddleware(keyHashHex: string | undefined): (_req: Request, _res: Response, next: NextFunction) => void;
3
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAM9D,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,UAGjD,OAAO,QAAQ,QAAQ,QAAQ,YAAY,KAAG,IAAI,CAuBnE"}
@@ -0,0 +1,32 @@
1
+ // auth.ts — Bearer token authentication middleware
2
+ //
3
+ // Accepts a pre-computed SHA-256 hex digest of the API key (keyHashHex).
4
+ // Every request must include an `Authorization: Bearer <key>` header whose
5
+ // SHA-256 hash matches the stored digest.
6
+ // When keyHashHex is absent the server runs in dev mode (all requests pass).
7
+ import { createHash, timingSafeEqual } from 'crypto';
8
+ function sha256(input) {
9
+ return createHash('sha256').update(input, 'utf8').digest();
10
+ }
11
+ export function createAuthMiddleware(keyHashHex) {
12
+ if (!keyHashHex) {
13
+ // Dev mode — no key configured, pass all requests
14
+ return (_req, _res, next) => next();
15
+ }
16
+ const expectedHash = Buffer.from(keyHashHex, 'hex');
17
+ return (req, res, next) => {
18
+ const authHeader = req.headers['authorization'];
19
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
20
+ res.status(401).json({ error: 'Authorization required' });
21
+ return;
22
+ }
23
+ const token = authHeader.slice(7);
24
+ const tokenHash = sha256(token);
25
+ if (tokenHash.length !== expectedHash.length || !timingSafeEqual(tokenHash, expectedHash)) {
26
+ res.status(401).json({ error: 'Invalid API key' });
27
+ return;
28
+ }
29
+ next();
30
+ };
31
+ }
32
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,EAAE;AACF,yEAAyE;AACzE,2EAA2E;AAC3E,0CAA0C;AAC1C,6EAA6E;AAE7E,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAA;AAGpD,SAAS,MAAM,CAAC,KAAa;IAC3B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE,CAAA;AAC5D,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,UAA8B;IACjE,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,kDAAkD;QAClD,OAAO,CAAC,IAAa,EAAE,IAAc,EAAE,IAAkB,EAAQ,EAAE,CAAC,IAAI,EAAE,CAAA;IAC5E,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAA;IAEnD,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAQ,EAAE;QAC/D,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAA;QAE/C,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACrD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC,CAAA;YACzD,OAAM;QACR,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QACjC,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;QAE/B,IAAI,SAAS,CAAC,MAAM,KAAK,YAAY,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,CAAC;YAC1F,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAA;YAClD,OAAM;QACR,CAAC;QAED,IAAI,EAAE,CAAA;IACR,CAAC,CAAA;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=auth.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.test.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,77 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { createHash } from 'crypto';
3
+ import express from 'express';
4
+ import http from 'http';
5
+ import { createAuthMiddleware } from './auth.js';
6
+ function sha256hex(input) {
7
+ return createHash('sha256').update(input, 'utf8').digest('hex');
8
+ }
9
+ async function startServer(apiKey) {
10
+ const app = express();
11
+ app.use(createAuthMiddleware(apiKey ? sha256hex(apiKey) : undefined));
12
+ app.get('/ping', (_req, res) => res.json({ ok: true }));
13
+ const server = http.createServer(app);
14
+ const port = await new Promise(resolve => server.listen(0, () => resolve(server.address().port)));
15
+ return { url: `http://localhost:${port}`, server };
16
+ }
17
+ async function get(url, headers = {}) {
18
+ const res = await fetch(url, { headers });
19
+ const body = await res.json();
20
+ return { status: res.status, body };
21
+ }
22
+ describe('createAuthMiddleware', () => {
23
+ it('passes all requests when no API key is configured (dev mode)', async () => {
24
+ const { url, server } = await startServer(undefined);
25
+ try {
26
+ const { status } = await get(`${url}/ping`);
27
+ expect(status).toBe(200);
28
+ }
29
+ finally {
30
+ await new Promise(r => server.close(() => r()));
31
+ }
32
+ });
33
+ it('returns 401 when Authorization header is missing', async () => {
34
+ const { url, server } = await startServer('my-secret-key');
35
+ try {
36
+ const { status, body } = await get(`${url}/ping`);
37
+ expect(status).toBe(401);
38
+ expect(body).toMatchObject({ error: 'Authorization required' });
39
+ }
40
+ finally {
41
+ await new Promise(r => server.close(() => r()));
42
+ }
43
+ });
44
+ it('returns 401 when Authorization header is not Bearer scheme', async () => {
45
+ const { url, server } = await startServer('my-secret-key');
46
+ try {
47
+ const { status } = await get(`${url}/ping`, { Authorization: 'Basic abc123' });
48
+ expect(status).toBe(401);
49
+ }
50
+ finally {
51
+ await new Promise(r => server.close(() => r()));
52
+ }
53
+ });
54
+ it('returns 401 for a wrong Bearer token', async () => {
55
+ const { url, server } = await startServer('my-secret-key');
56
+ try {
57
+ const { status, body } = await get(`${url}/ping`, { Authorization: 'Bearer wrong-key' });
58
+ expect(status).toBe(401);
59
+ expect(body).toMatchObject({ error: 'Invalid API key' });
60
+ }
61
+ finally {
62
+ await new Promise(r => server.close(() => r()));
63
+ }
64
+ });
65
+ it('passes request with the correct Bearer token', async () => {
66
+ const { url, server } = await startServer('my-secret-key');
67
+ try {
68
+ const { status, body } = await get(`${url}/ping`, { Authorization: 'Bearer my-secret-key' });
69
+ expect(status).toBe(200);
70
+ expect(body).toMatchObject({ ok: true });
71
+ }
72
+ finally {
73
+ await new Promise(r => server.close(() => r()));
74
+ }
75
+ });
76
+ });
77
+ //# sourceMappingURL=auth.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.test.js","sourceRoot":"","sources":["../../src/middleware/auth.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=remote-store.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-store.test.d.ts","sourceRoot":"","sources":["../src/remote-store.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,256 @@
1
+ // Integration test: RemoteStore ↔ LocalStore
2
+ //
3
+ // Scenario: spin up an Express server with the store router backed by an
4
+ // in-memory LocalStore, then run CRUD through a RemoteStore client and verify
5
+ // the results match what LocalStore returns directly.
6
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
7
+ import express from 'express';
8
+ import http from 'http';
9
+ import { LocalStore, RemoteStore } from '@contextgit/store';
10
+ import { createStoreRouter } from './store-router.js';
11
+ describe('RemoteStore ↔ LocalStore integration', () => {
12
+ let server;
13
+ let localStore;
14
+ let remote;
15
+ beforeAll(async () => {
16
+ localStore = new LocalStore(':memory:');
17
+ const app = express();
18
+ app.use(express.json());
19
+ app.use('/v1/store', createStoreRouter(localStore));
20
+ server = http.createServer(app);
21
+ const port = await new Promise(resolve => server.listen(0, () => resolve(server.address().port)));
22
+ remote = new RemoteStore(`http://localhost:${port}`);
23
+ });
24
+ afterAll(() => {
25
+ return new Promise(resolve => {
26
+ server.close(() => {
27
+ localStore.close();
28
+ resolve();
29
+ });
30
+ });
31
+ });
32
+ it('creates and retrieves a project via RemoteStore', async () => {
33
+ const project = await remote.createProject({ name: 'remote-test', description: 'HTTP project' });
34
+ expect(project.id).toBeTruthy();
35
+ expect(project.name).toBe('remote-test');
36
+ expect(project.createdAt).toBeInstanceOf(Date);
37
+ // Directly confirm it's in LocalStore
38
+ const local = await localStore.getProject(project.id);
39
+ expect(local?.name).toBe('remote-test');
40
+ });
41
+ it('creates a branch and retrieves by git name', async () => {
42
+ const project = await remote.createProject({ name: 'branch-proj' });
43
+ const branch = await remote.createBranch({
44
+ projectId: project.id,
45
+ name: 'main',
46
+ gitBranch: 'main',
47
+ });
48
+ expect(branch.id).toBeTruthy();
49
+ expect(branch.gitBranch).toBe('main');
50
+ expect(branch.createdAt).toBeInstanceOf(Date);
51
+ const byGit = await remote.getBranchByGitName(project.id, 'main');
52
+ expect(byGit?.id).toBe(branch.id);
53
+ const notFound = await remote.getBranchByGitName(project.id, 'nonexistent');
54
+ expect(notFound).toBeNull();
55
+ });
56
+ it('creates a commit and retrieves it', async () => {
57
+ const project = await remote.createProject({ name: 'commit-proj' });
58
+ const branch = await remote.createBranch({ projectId: project.id, name: 'main', gitBranch: 'main' });
59
+ await remote.upsertAgent({
60
+ id: 'agent-remote',
61
+ projectId: project.id,
62
+ role: 'dev',
63
+ tool: 'test',
64
+ workflowType: 'interactive',
65
+ });
66
+ const commit = await remote.createCommit({
67
+ branchId: branch.id,
68
+ agentId: 'agent-remote',
69
+ agentRole: 'dev',
70
+ tool: 'test',
71
+ workflowType: 'interactive',
72
+ message: 'Remote commit',
73
+ content: 'Content via HTTP',
74
+ summary: 'Summary',
75
+ commitType: 'manual',
76
+ });
77
+ expect(commit.id).toBeTruthy();
78
+ expect(commit.message).toBe('Remote commit');
79
+ expect(commit.createdAt).toBeInstanceOf(Date);
80
+ const fetched = await remote.getCommit(commit.id);
81
+ expect(fetched?.message).toBe('Remote commit');
82
+ });
83
+ it('getFormattedSnapshot via RemoteStore matches LocalStore output', async () => {
84
+ const project = await remote.createProject({ name: 'snap-proj' });
85
+ const branch = await remote.createBranch({ projectId: project.id, name: 'main', gitBranch: 'main' });
86
+ await remote.upsertAgent({
87
+ id: 'snap-agent',
88
+ projectId: project.id,
89
+ role: 'dev',
90
+ tool: 'test',
91
+ workflowType: 'interactive',
92
+ });
93
+ await remote.createCommit({
94
+ branchId: branch.id,
95
+ agentId: 'snap-agent',
96
+ agentRole: 'dev',
97
+ tool: 'test',
98
+ workflowType: 'interactive',
99
+ message: 'First commit',
100
+ content: 'Setting things up',
101
+ summary: 'Project scaffolded',
102
+ commitType: 'manual',
103
+ });
104
+ const remoteSnapshot = await remote.getFormattedSnapshot(project.id, branch.id, 'text');
105
+ const localSnapshot = await localStore.getFormattedSnapshot(project.id, branch.id, 'text');
106
+ // Both should contain the expected sections
107
+ expect(remoteSnapshot).toContain('=== PROJECT STATE ===');
108
+ expect(remoteSnapshot).toContain('Project scaffolded');
109
+ // RemoteStore and LocalStore return the same formatted text
110
+ expect(remoteSnapshot).toBe(localSnapshot);
111
+ });
112
+ it('open threads round-trip via RemoteStore', async () => {
113
+ const project = await remote.createProject({ name: 'thread-proj' });
114
+ const branch = await remote.createBranch({ projectId: project.id, name: 'main', gitBranch: 'main' });
115
+ await remote.upsertAgent({
116
+ id: 'thread-agent',
117
+ projectId: project.id,
118
+ role: 'dev',
119
+ tool: 'test',
120
+ workflowType: 'interactive',
121
+ });
122
+ await remote.createCommit({
123
+ branchId: branch.id,
124
+ agentId: 'thread-agent',
125
+ agentRole: 'dev',
126
+ tool: 'test',
127
+ workflowType: 'interactive',
128
+ message: 'Open a thread',
129
+ content: 'Some work',
130
+ summary: 'Work in progress',
131
+ commitType: 'manual',
132
+ threads: { open: ['Which auth approach to use?'] },
133
+ });
134
+ const threads = await remote.listOpenThreads(project.id);
135
+ expect(threads).toHaveLength(1);
136
+ expect(threads[0].description).toBe('Which auth approach to use?');
137
+ expect(threads[0].createdAt).toBeInstanceOf(Date);
138
+ });
139
+ it('fullTextSearch returns results via RemoteStore', async () => {
140
+ const project = await remote.createProject({ name: 'search-proj' });
141
+ const branch = await remote.createBranch({ projectId: project.id, name: 'main', gitBranch: 'main' });
142
+ await remote.upsertAgent({
143
+ id: 'search-agent',
144
+ projectId: project.id,
145
+ role: 'dev',
146
+ tool: 'test',
147
+ workflowType: 'interactive',
148
+ });
149
+ await remote.createCommit({
150
+ branchId: branch.id,
151
+ agentId: 'search-agent',
152
+ agentRole: 'dev',
153
+ tool: 'test',
154
+ workflowType: 'interactive',
155
+ message: 'Add authentication',
156
+ content: 'Implemented JWT RS256 for authentication',
157
+ summary: 'JWT auth done',
158
+ commitType: 'manual',
159
+ });
160
+ const results = await remote.fullTextSearch('JWT', project.id);
161
+ expect(results.length).toBeGreaterThan(0);
162
+ expect(results[0].commit.createdAt).toBeInstanceOf(Date);
163
+ expect(results[0].matchType).toBe('fulltext');
164
+ });
165
+ it('mergeBranch carries threads via RemoteStore', async () => {
166
+ const project = await remote.createProject({ name: 'merge-proj' });
167
+ const main = await remote.createBranch({ projectId: project.id, name: 'main', gitBranch: 'main' });
168
+ const feat = await remote.createBranch({
169
+ projectId: project.id,
170
+ name: 'feat',
171
+ gitBranch: 'feat',
172
+ parentBranchId: main.id,
173
+ });
174
+ await remote.upsertAgent({
175
+ id: 'merge-agent',
176
+ projectId: project.id,
177
+ role: 'dev',
178
+ tool: 'test',
179
+ workflowType: 'interactive',
180
+ });
181
+ await remote.createCommit({
182
+ branchId: main.id,
183
+ agentId: 'merge-agent',
184
+ agentRole: 'dev',
185
+ tool: 'test',
186
+ workflowType: 'interactive',
187
+ message: 'main init',
188
+ content: 'c',
189
+ summary: 's',
190
+ commitType: 'branch-init',
191
+ });
192
+ await remote.createCommit({
193
+ branchId: feat.id,
194
+ agentId: 'merge-agent',
195
+ agentRole: 'dev',
196
+ tool: 'test',
197
+ workflowType: 'interactive',
198
+ message: 'feat work',
199
+ content: 'c',
200
+ summary: 's',
201
+ commitType: 'manual',
202
+ threads: { open: ['Thread from feat'] },
203
+ });
204
+ const mergeCommit = await remote.mergeBranch(feat.id, main.id, 'Merged feat into main');
205
+ expect(mergeCommit.commitType).toBe('merge');
206
+ expect(mergeCommit.createdAt).toBeInstanceOf(Date);
207
+ // Source branch is merged
208
+ const updatedFeat = await remote.getBranch(feat.id);
209
+ expect(updatedFeat?.status).toBe('merged');
210
+ // Thread carried to main branch
211
+ const mainThreads = await remote.listOpenThreadsByBranch(main.id);
212
+ expect(mainThreads).toHaveLength(1);
213
+ expect(mainThreads[0].description).toBe('Thread from feat');
214
+ });
215
+ it('syncThread is idempotent and round-trips via RemoteStore', async () => {
216
+ const project = await remote.createProject({ name: 'sync-thread-proj' });
217
+ const branch = await remote.createBranch({ projectId: project.id, name: 'main', gitBranch: 'main' });
218
+ await remote.upsertAgent({
219
+ id: 'sync-agent',
220
+ projectId: project.id,
221
+ role: 'dev',
222
+ tool: 'test',
223
+ workflowType: 'interactive',
224
+ });
225
+ // Create a commit so we have a valid openedInCommit reference
226
+ const commit = await remote.createCommit({
227
+ branchId: branch.id,
228
+ agentId: 'sync-agent',
229
+ agentRole: 'dev',
230
+ tool: 'test',
231
+ workflowType: 'interactive',
232
+ message: 'Seed commit',
233
+ content: 'c',
234
+ summary: 's',
235
+ commitType: 'manual',
236
+ });
237
+ // Construct a Thread as if it came from another store (e.g. during push/pull)
238
+ const thread = await remote.syncThread({
239
+ id: 'sync-thread-id-1',
240
+ projectId: project.id,
241
+ branchId: branch.id,
242
+ description: 'Synced open question',
243
+ status: 'open',
244
+ openedInCommit: commit.id,
245
+ createdAt: new Date(),
246
+ });
247
+ expect(thread.id).toBe('sync-thread-id-1');
248
+ expect(thread.description).toBe('Synced open question');
249
+ // Idempotent: calling again should not throw
250
+ await expect(remote.syncThread(thread)).resolves.toBeDefined();
251
+ // Thread visible via listOpenThreads
252
+ const open = await remote.listOpenThreads(project.id);
253
+ expect(open.some(t => t.id === 'sync-thread-id-1')).toBe(true);
254
+ });
255
+ });
256
+ //# sourceMappingURL=remote-store.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-store.test.js","sourceRoot":"","sources":["../src/remote-store.test.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,EAAE;AACF,yEAAyE;AACzE,8EAA8E;AAC9E,sDAAsD;AAEtD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAClE,OAAO,OAAO,MAAM,SAAS,CAAA;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAErD,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;IACpD,IAAI,MAAmB,CAAA;IACvB,IAAI,UAAsB,CAAA;IAC1B,IAAI,MAAmB,CAAA;IAEvB,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,UAAU,GAAG,IAAI,UAAU,CAAC,UAAU,CAAC,CAAA;QAEvC,MAAM,GAAG,GAAG,OAAO,EAAE,CAAA;QACrB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;QACvB,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAA;QAEnD,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAA;QAC/B,MAAM,IAAI,GAAG,MAAM,IAAI,OAAO,CAAS,OAAO,CAAC,EAAE,CAC/C,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,OAAO,CAAE,MAAM,CAAC,OAAO,EAAkB,CAAC,IAAI,CAAC,CAAC,CACxE,CAAA;QAED,MAAM,GAAG,IAAI,WAAW,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAA;IACtD,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,GAAG,EAAE;QACZ,OAAO,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE;YACjC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE;gBAChB,UAAU,CAAC,KAAK,EAAE,CAAA;gBAClB,OAAO,EAAE,CAAA;YACX,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC,CAAA;QAChG,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,UAAU,EAAE,CAAA;QAC/B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QACxC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAA;QAE9C,sCAAsC;QACtC,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QACrD,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAA;QACnE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC;YACvC,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,IAAI,EAAE,MAAM;YACZ,SAAS,EAAE,MAAM;SAClB,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,UAAU,EAAE,CAAA;QAC9B,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACrC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAA;QAE7C,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;QACjE,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QAEjC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,EAAE,aAAa,CAAC,CAAA;QAC3E,MAAM,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAA;IAC7B,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAA;QACnE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAA;QAEpG,MAAM,MAAM,CAAC,WAAW,CAAC;YACvB,EAAE,EAAE,cAAc;YAClB,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,MAAM;YACZ,YAAY,EAAE,aAAa;SAC5B,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC;YACvC,QAAQ,EAAE,MAAM,CAAC,EAAE;YACnB,OAAO,EAAE,cAAc;YACvB,SAAS,EAAE,KAAK;YAChB,IAAI,EAAE,MAAM;YACZ,YAAY,EAAE,aAAa;YAC3B,OAAO,EAAE,eAAe;YACxB,OAAO,EAAE,kBAAkB;YAC3B,OAAO,EAAE,SAAS;YAClB,UAAU,EAAE,QAAQ;SACrB,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,UAAU,EAAE,CAAA;QAC9B,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;QAC5C,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAA;QAE7C,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QACjD,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAA;QACjE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAA;QAEpG,MAAM,MAAM,CAAC,WAAW,CAAC;YACvB,EAAE,EAAE,YAAY;YAChB,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,MAAM;YACZ,YAAY,EAAE,aAAa;SAC5B,CAAC,CAAA;QAEF,MAAM,MAAM,CAAC,YAAY,CAAC;YACxB,QAAQ,EAAE,MAAM,CAAC,EAAE;YACnB,OAAO,EAAE,YAAY;YACrB,SAAS,EAAE,KAAK;YAChB,IAAI,EAAE,MAAM;YACZ,YAAY,EAAE,aAAa;YAC3B,OAAO,EAAE,cAAc;YACvB,OAAO,EAAE,mBAAmB;YAC5B,OAAO,EAAE,oBAAoB;YAC7B,UAAU,EAAE,QAAQ;SACrB,CAAC,CAAA;QAEF,MAAM,cAAc,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;QACvF,MAAM,aAAa,GAAG,MAAM,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;QAE1F,4CAA4C;QAC5C,MAAM,CAAC,cAAc,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAA;QACzD,MAAM,CAAC,cAAc,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAA;QAEtD,4DAA4D;QAC5D,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IAC5C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAA;QACnE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAA;QAEpG,MAAM,MAAM,CAAC,WAAW,CAAC;YACvB,EAAE,EAAE,cAAc;YAClB,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,MAAM;YACZ,YAAY,EAAE,aAAa;SAC5B,CAAC,CAAA;QAEF,MAAM,MAAM,CAAC,YAAY,CAAC;YACxB,QAAQ,EAAE,MAAM,CAAC,EAAE;YACnB,OAAO,EAAE,cAAc;YACvB,SAAS,EAAE,KAAK;YAChB,IAAI,EAAE,MAAM;YACZ,YAAY,EAAE,aAAa;YAC3B,OAAO,EAAE,eAAe;YACxB,OAAO,EAAE,WAAW;YACpB,OAAO,EAAE,kBAAkB;YAC3B,UAAU,EAAE,QAAQ;YACpB,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,6BAA6B,CAAC,EAAE;SACnD,CAAC,CAAA;QAEF,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QACxD,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAC/B,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAA;QAClE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAA;QACnE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAA;QAEpG,MAAM,MAAM,CAAC,WAAW,CAAC;YACvB,EAAE,EAAE,cAAc;YAClB,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,MAAM;YACZ,YAAY,EAAE,aAAa;SAC5B,CAAC,CAAA;QAEF,MAAM,MAAM,CAAC,YAAY,CAAC;YACxB,QAAQ,EAAE,MAAM,CAAC,EAAE;YACnB,OAAO,EAAE,cAAc;YACvB,SAAS,EAAE,KAAK;YAChB,IAAI,EAAE,MAAM;YACZ,YAAY,EAAE,aAAa;YAC3B,OAAO,EAAE,oBAAoB;YAC7B,OAAO,EAAE,0CAA0C;YACnD,OAAO,EAAE,eAAe;YACxB,UAAU,EAAE,QAAQ;SACrB,CAAC,CAAA;QAEF,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC,CAAA;QAC9D,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;QACzC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAA;QACxD,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAC/C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAA;QAClE,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAA;QAClG,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC;YACrC,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,IAAI,EAAE,MAAM;YACZ,SAAS,EAAE,MAAM;YACjB,cAAc,EAAE,IAAI,CAAC,EAAE;SACxB,CAAC,CAAA;QAEF,MAAM,MAAM,CAAC,WAAW,CAAC;YACvB,EAAE,EAAE,aAAa;YACjB,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,MAAM;YACZ,YAAY,EAAE,aAAa;SAC5B,CAAC,CAAA;QAEF,MAAM,MAAM,CAAC,YAAY,CAAC;YACxB,QAAQ,EAAE,IAAI,CAAC,EAAE;YACjB,OAAO,EAAE,aAAa;YACtB,SAAS,EAAE,KAAK;YAChB,IAAI,EAAE,MAAM;YACZ,YAAY,EAAE,aAAa;YAC3B,OAAO,EAAE,WAAW;YACpB,OAAO,EAAE,GAAG;YACZ,OAAO,EAAE,GAAG;YACZ,UAAU,EAAE,aAAa;SAC1B,CAAC,CAAA;QAEF,MAAM,MAAM,CAAC,YAAY,CAAC;YACxB,QAAQ,EAAE,IAAI,CAAC,EAAE;YACjB,OAAO,EAAE,aAAa;YACtB,SAAS,EAAE,KAAK;YAChB,IAAI,EAAE,MAAM;YACZ,YAAY,EAAE,aAAa;YAC3B,OAAO,EAAE,WAAW;YACpB,OAAO,EAAE,GAAG;YACZ,OAAO,EAAE,GAAG;YACZ,UAAU,EAAE,QAAQ;YACpB,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,kBAAkB,CAAC,EAAE;SACxC,CAAC,CAAA;QAEF,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,uBAAuB,CAAC,CAAA;QACvF,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC5C,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAA;QAElD,0BAA0B;QAC1B,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACnD,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAE1C,gCAAgC;QAChC,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACjE,MAAM,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QACnC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;IAC7D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,CAAA;QACxE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAA;QAEpG,MAAM,MAAM,CAAC,WAAW,CAAC;YACvB,EAAE,EAAE,YAAY;YAChB,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,MAAM;YACZ,YAAY,EAAE,aAAa;SAC5B,CAAC,CAAA;QAEF,8DAA8D;QAC9D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC;YACvC,QAAQ,EAAE,MAAM,CAAC,EAAE;YACnB,OAAO,EAAE,YAAY;YACrB,SAAS,EAAE,KAAK;YAChB,IAAI,EAAE,MAAM;YACZ,YAAY,EAAE,aAAa;YAC3B,OAAO,EAAE,aAAa;YACtB,OAAO,EAAE,GAAG;YACZ,OAAO,EAAE,GAAG;YACZ,UAAU,EAAE,QAAQ;SACrB,CAAC,CAAA;QAEF,8EAA8E;QAC9E,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC;YACrC,EAAE,EAAE,kBAAkB;YACtB,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,QAAQ,EAAE,MAAM,CAAC,EAAE;YACnB,WAAW,EAAE,sBAAsB;YACnC,MAAM,EAAE,MAAM;YACd,cAAc,EAAE,MAAM,CAAC,EAAE;YACzB,SAAS,EAAE,IAAI,IAAI,EAAE;SACtB,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;QAC1C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;QAEvD,6CAA6C;QAC7C,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAA;QAE9D,qCAAqC;QACrC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QACrD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAChE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,4 @@
1
+ import { Router } from 'express';
2
+ import type { ApiContext } from './bootstrap.js';
3
+ export declare function createRouter(ctx: ApiContext): Router;
4
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAA;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAGhD,wBAAgB,YAAY,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CA6GpD"}
package/dist/router.js ADDED
@@ -0,0 +1,103 @@
1
+ // router.ts — Express router for ContextGit REST API
2
+ //
3
+ // Routes:
4
+ // POST /commits — engine.commit() — persist a context commit
5
+ // GET /snapshot — store.getFormattedSnapshot() — formatted project snapshot
6
+ // GET /search — store.fullTextSearch() — full-text search over commits
7
+ import { Router } from 'express';
8
+ export function createRouter(ctx) {
9
+ const router = Router();
10
+ // ── POST /commits ──────────────────────────────────────────────────────────
11
+ // Body: { message, content, open_threads?, close_thread_ids? }
12
+ router.post('/commits', async (req, res) => {
13
+ try {
14
+ const { message, content, open_threads, close_thread_ids } = req.body;
15
+ if (typeof message !== 'string' || message.trim() === '') {
16
+ res.status(400).json({ error: "'message' is required and must be a non-empty string" });
17
+ return;
18
+ }
19
+ if (typeof content !== 'string' || content.trim() === '') {
20
+ res.status(400).json({ error: "'content' is required and must be a non-empty string" });
21
+ return;
22
+ }
23
+ const threads = {};
24
+ if (Array.isArray(open_threads) && open_threads.length > 0) {
25
+ threads.open = open_threads.map(String);
26
+ }
27
+ if (Array.isArray(close_thread_ids) && close_thread_ids.length > 0) {
28
+ threads.close = close_thread_ids.map((id) => ({
29
+ id: String(id),
30
+ note: 'Closed via API',
31
+ }));
32
+ }
33
+ const commit = await ctx.engine.commit({
34
+ message,
35
+ content,
36
+ ...(Object.keys(threads).length > 0 ? { threads } : {}),
37
+ });
38
+ res.status(201).json({ id: commit.id, message: commit.message, createdAt: commit.createdAt });
39
+ }
40
+ catch (err) {
41
+ const message = err instanceof Error ? err.message : String(err);
42
+ res.status(500).json({ error: message });
43
+ }
44
+ });
45
+ // ── GET /snapshot ──────────────────────────────────────────────────────────
46
+ // Query: ?format=agents-md|json|text (default: agents-md)
47
+ router.get('/snapshot', async (req, res) => {
48
+ try {
49
+ const format = (req.query['format'] ?? 'agents-md');
50
+ const validFormats = ['agents-md', 'json', 'text'];
51
+ if (!validFormats.includes(format)) {
52
+ res.status(400).json({ error: `'format' must be one of: ${validFormats.join(', ')}` });
53
+ return;
54
+ }
55
+ const snapshot = await ctx.store.getFormattedSnapshot(ctx.projectId, ctx.branchId, format);
56
+ if (format === 'json') {
57
+ res.setHeader('Content-Type', 'application/json');
58
+ res.send(snapshot);
59
+ }
60
+ else {
61
+ res.setHeader('Content-Type', 'text/plain; charset=utf-8');
62
+ res.send(snapshot);
63
+ }
64
+ }
65
+ catch (err) {
66
+ const message = err instanceof Error ? err.message : String(err);
67
+ res.status(500).json({ error: message });
68
+ }
69
+ });
70
+ // ── GET /search ────────────────────────────────────────────────────────────
71
+ // Query: ?q=<query>&limit=<n> (limit default: 5, max: 20)
72
+ router.get('/search', async (req, res) => {
73
+ try {
74
+ const q = req.query['q'];
75
+ if (typeof q !== 'string' || q.trim() === '') {
76
+ res.status(400).json({ error: "'q' query parameter is required" });
77
+ return;
78
+ }
79
+ const limitRaw = parseInt(String(req.query['limit'] ?? '5'), 10);
80
+ const limit = Number.isNaN(limitRaw) ? 5 : Math.min(Math.max(limitRaw, 1), 20);
81
+ const results = await ctx.store.fullTextSearch(q, ctx.projectId);
82
+ const trimmed = results.slice(0, limit);
83
+ res.json({
84
+ query: q,
85
+ total: trimmed.length,
86
+ results: trimmed.map(r => ({
87
+ id: r.commit.id,
88
+ message: r.commit.message,
89
+ content: r.commit.content,
90
+ score: r.score,
91
+ matchType: r.matchType,
92
+ createdAt: r.commit.createdAt,
93
+ })),
94
+ });
95
+ }
96
+ catch (err) {
97
+ const message = err instanceof Error ? err.message : String(err);
98
+ res.status(500).json({ error: message });
99
+ }
100
+ });
101
+ return router;
102
+ }
103
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface ServerConfig {
2
+ keyHash?: string;
3
+ }
4
+ export declare function sha256hex(input: string): string;
5
+ export declare function readServerConfig(): ServerConfig;
6
+ export declare function writeServerConfig(config: ServerConfig): void;
7
+ //# sourceMappingURL=server-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../src/server-config.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,gBAAgB,IAAI,YAAY,CAO/C;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAG5D"}
@@ -0,0 +1,27 @@
1
+ // server-config.ts — global server configuration at ~/.contextgit/server.json
2
+ //
3
+ // Stores the SHA-256 hash of the API key so the plaintext key never rests on disk.
4
+ // The server reads the hash on startup; keygen --save writes it.
5
+ import os from 'os';
6
+ import { join } from 'path';
7
+ import { mkdirSync, readFileSync, writeFileSync } from 'fs';
8
+ import { createHash } from 'crypto';
9
+ const CONTEXTGIT_DIR = join(os.homedir(), '.contextgit');
10
+ const SERVER_CONFIG_PATH = join(CONTEXTGIT_DIR, 'server.json');
11
+ export function sha256hex(input) {
12
+ return createHash('sha256').update(input, 'utf8').digest('hex');
13
+ }
14
+ export function readServerConfig() {
15
+ try {
16
+ const raw = readFileSync(SERVER_CONFIG_PATH, 'utf-8');
17
+ return JSON.parse(raw);
18
+ }
19
+ catch {
20
+ return {};
21
+ }
22
+ }
23
+ export function writeServerConfig(config) {
24
+ mkdirSync(CONTEXTGIT_DIR, { recursive: true });
25
+ writeFileSync(SERVER_CONFIG_PATH, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 });
26
+ }
27
+ //# sourceMappingURL=server-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-config.js","sourceRoot":"","sources":["../src/server-config.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,EAAE;AACF,mFAAmF;AACnF,iEAAiE;AAEjE,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAEnC,MAAM,cAAc,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAA;AACxD,MAAM,kBAAkB,GAAG,IAAI,CAAC,cAAc,EAAE,aAAa,CAAC,CAAA;AAM9D,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACjE,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAA;QACrD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAiB,CAAA;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAoB;IACpD,SAAS,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC9C,aAAa,CAAC,kBAAkB,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;AAC5F,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Express } from 'express';
2
+ export declare function createApp(): Promise<Express>;
3
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAOtC,wBAAsB,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAwBlD"}
package/dist/server.js ADDED
@@ -0,0 +1,32 @@
1
+ // server.ts — ContextGit REST API server
2
+ //
3
+ // Creates and configures the Express app. Separated from index.ts so tests
4
+ // can import createApp() without binding to a port.
5
+ import express from 'express';
6
+ import { bootstrap } from './bootstrap.js';
7
+ import { createRouter } from './router.js';
8
+ import { createStoreRouter } from './store-router.js';
9
+ import { createAuthMiddleware } from './middleware/auth.js';
10
+ import { readServerConfig, sha256hex } from './server-config.js';
11
+ export async function createApp() {
12
+ const ctx = await bootstrap();
13
+ // Resolve key hash: prefer ~/.contextgit/server.json, fall back to env var
14
+ const serverCfg = readServerConfig();
15
+ let keyHashHex = serverCfg.keyHash;
16
+ if (!keyHashHex) {
17
+ const envKey = process.env['CONTEXTGIT_API_KEY'];
18
+ if (envKey)
19
+ keyHashHex = sha256hex(envKey);
20
+ }
21
+ const app = express();
22
+ app.use(express.json());
23
+ app.use(createAuthMiddleware(keyHashHex));
24
+ app.use('/v1/store', createStoreRouter(ctx.store));
25
+ app.use('/', createRouter(ctx));
26
+ // 404 catch-all
27
+ app.use((_req, res) => {
28
+ res.status(404).json({ error: 'Not found' });
29
+ });
30
+ return app;
31
+ }
32
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,oDAAoD;AAEpD,OAAO,OAAO,MAAM,SAAS,CAAA;AAE7B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAEhE,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,GAAG,GAAG,MAAM,SAAS,EAAE,CAAA;IAE7B,2EAA2E;IAC3E,MAAM,SAAS,GAAG,gBAAgB,EAAE,CAAA;IACpC,IAAI,UAAU,GAAG,SAAS,CAAC,OAAO,CAAA;IAClC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAA;QAChD,IAAI,MAAM;YAAE,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,CAAA;IAC5C,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,EAAE,CAAA;IACrB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;IACvB,GAAG,CAAC,GAAG,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC,CAAA;IAEzC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAA;IAClD,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAA;IAE/B,gBAAgB;IAChB,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QACpB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAA;IAC9C,CAAC,CAAC,CAAA;IAEF,OAAO,GAAG,CAAA;AACZ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Router } from 'express';
2
+ import type { ContextStore } from '@contextgit/store';
3
+ export declare function createStoreRouter(store: ContextStore): Router;
4
+ //# sourceMappingURL=store-router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store-router.d.ts","sourceRoot":"","sources":["../src/store-router.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAgBrD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAqM7D"}
@@ -0,0 +1,281 @@
1
+ // store-router.ts — Express router providing direct ContextStore access over HTTP.
2
+ //
3
+ // Mounted at a path prefix (e.g. /v1/store). Used by RemoteStore clients.
4
+ //
5
+ // Routes:
6
+ // POST /projects → createProject
7
+ // GET /projects/:id → getProject
8
+ // POST /branches → createBranch
9
+ // GET /branches/:id → getBranch
10
+ // GET /projects/:projectId/branches?git= → getBranchByGitName
11
+ // GET /projects/:projectId/branches → listBranches
12
+ // PUT /branches/:id/head → updateBranchHead
13
+ // POST /branches/:id/merge → mergeBranch
14
+ // POST /commits → createCommit
15
+ // GET /commits/:id → getCommit
16
+ // GET /branches/:branchId/commits → listCommits
17
+ // GET /projects/:id/snapshot → getFormattedSnapshot
18
+ // GET /projects/:id/session-snapshot → getSessionSnapshot
19
+ // GET /projects/:id/threads → listOpenThreads
20
+ // GET /branches/:branchId/threads → listOpenThreadsByBranch
21
+ // POST /commits/:id/embedding → indexEmbedding
22
+ // POST /projects/:id/search/semantic → semanticSearch
23
+ // GET /projects/:id/search → fullTextSearch
24
+ // POST /agents → upsertAgent
25
+ // GET /projects/:id/agents → listAgents
26
+ import { Router } from 'express';
27
+ function err(res, e) {
28
+ const msg = e instanceof Error ? e.message : String(e);
29
+ res.status(500).json({ error: msg });
30
+ }
31
+ export function createStoreRouter(store) {
32
+ const r = Router();
33
+ // ── Projects ──────────────────────────────────────────────────────────────
34
+ r.post('/projects', async (req, res) => {
35
+ try {
36
+ const result = await store.createProject(req.body);
37
+ res.status(201).json(result);
38
+ }
39
+ catch (e) {
40
+ err(res, e);
41
+ }
42
+ });
43
+ r.get('/projects/:id', async (req, res) => {
44
+ try {
45
+ const result = await store.getProject(req.params['id']);
46
+ if (!result) {
47
+ res.status(404).json({ error: 'Not found' });
48
+ return;
49
+ }
50
+ res.json(result);
51
+ }
52
+ catch (e) {
53
+ err(res, e);
54
+ }
55
+ });
56
+ // ── Branches ──────────────────────────────────────────────────────────────
57
+ r.post('/branches', async (req, res) => {
58
+ try {
59
+ const result = await store.createBranch(req.body);
60
+ res.status(201).json(result);
61
+ }
62
+ catch (e) {
63
+ err(res, e);
64
+ }
65
+ });
66
+ r.get('/branches/:id', async (req, res) => {
67
+ try {
68
+ const result = await store.getBranch(req.params['id']);
69
+ if (!result) {
70
+ res.status(404).json({ error: 'Not found' });
71
+ return;
72
+ }
73
+ res.json(result);
74
+ }
75
+ catch (e) {
76
+ err(res, e);
77
+ }
78
+ });
79
+ // GET /projects/:projectId/branches?git=<name> → getBranchByGitName
80
+ // GET /projects/:projectId/branches → listBranches
81
+ r.get('/projects/:projectId/branches', async (req, res) => {
82
+ try {
83
+ const { projectId } = req.params;
84
+ const git = req.query['git'];
85
+ if (git) {
86
+ const result = await store.getBranchByGitName(projectId, git);
87
+ if (!result) {
88
+ res.status(404).json({ error: 'Not found' });
89
+ return;
90
+ }
91
+ res.json(result);
92
+ }
93
+ else {
94
+ const result = await store.listBranches(projectId);
95
+ res.json(result);
96
+ }
97
+ }
98
+ catch (e) {
99
+ err(res, e);
100
+ }
101
+ });
102
+ r.put('/branches/:id/head', async (req, res) => {
103
+ try {
104
+ const { commitId } = req.body;
105
+ await store.updateBranchHead(req.params['id'], commitId);
106
+ res.status(204).end();
107
+ }
108
+ catch (e) {
109
+ err(res, e);
110
+ }
111
+ });
112
+ r.post('/branches/:id/merge', async (req, res) => {
113
+ try {
114
+ const { targetBranchId, summary } = req.body;
115
+ const result = await store.mergeBranch(req.params['id'], targetBranchId, summary);
116
+ res.status(201).json(result);
117
+ }
118
+ catch (e) {
119
+ err(res, e);
120
+ }
121
+ });
122
+ // ── Commits ───────────────────────────────────────────────────────────────
123
+ r.post('/commits', async (req, res) => {
124
+ try {
125
+ const result = await store.createCommit(req.body);
126
+ res.status(201).json(result);
127
+ }
128
+ catch (e) {
129
+ err(res, e);
130
+ }
131
+ });
132
+ r.get('/commits/:id', async (req, res) => {
133
+ try {
134
+ const result = await store.getCommit(req.params['id']);
135
+ if (!result) {
136
+ res.status(404).json({ error: 'Not found' });
137
+ return;
138
+ }
139
+ res.json(result);
140
+ }
141
+ catch (e) {
142
+ err(res, e);
143
+ }
144
+ });
145
+ r.get('/branches/:branchId/commits', async (req, res) => {
146
+ try {
147
+ const pagination = {
148
+ limit: parseInt(String(req.query['limit'] ?? '10'), 10),
149
+ offset: parseInt(String(req.query['offset'] ?? '0'), 10),
150
+ };
151
+ const result = await store.listCommits(req.params['branchId'], pagination);
152
+ res.json(result);
153
+ }
154
+ catch (e) {
155
+ err(res, e);
156
+ }
157
+ });
158
+ // ── Snapshots ─────────────────────────────────────────────────────────────
159
+ // GET /projects/:id/snapshot?branchId=&format= → getFormattedSnapshot
160
+ r.get('/projects/:id/snapshot', async (req, res) => {
161
+ try {
162
+ const projectId = req.params['id'];
163
+ const branchId = String(req.query['branchId'] ?? '');
164
+ const format = String(req.query['format'] ?? 'text');
165
+ if (!branchId) {
166
+ res.status(400).json({ error: "'branchId' query param required" });
167
+ return;
168
+ }
169
+ const result = await store.getFormattedSnapshot(projectId, branchId, format);
170
+ const ct = format === 'json' ? 'application/json' : 'text/plain; charset=utf-8';
171
+ res.setHeader('Content-Type', ct).send(result);
172
+ }
173
+ catch (e) {
174
+ err(res, e);
175
+ }
176
+ });
177
+ // GET /projects/:id/session-snapshot?branchId= → getSessionSnapshot
178
+ r.get('/projects/:id/session-snapshot', async (req, res) => {
179
+ try {
180
+ const projectId = req.params['id'];
181
+ const branchId = String(req.query['branchId'] ?? '');
182
+ if (!branchId) {
183
+ res.status(400).json({ error: "'branchId' query param required" });
184
+ return;
185
+ }
186
+ const agentRole = req.query['agentRole'] ? String(req.query['agentRole']) : undefined;
187
+ const result = await store.getSessionSnapshot(projectId, branchId, agentRole ? { agentRole: agentRole } : undefined);
188
+ res.json(result);
189
+ }
190
+ catch (e) {
191
+ err(res, e);
192
+ }
193
+ });
194
+ // ── Threads ───────────────────────────────────────────────────────────────
195
+ r.post('/threads', async (req, res) => {
196
+ try {
197
+ const body = req.body;
198
+ // Parse createdAt from ISO string to Date
199
+ const thread = { ...body, createdAt: new Date(body.createdAt) };
200
+ const result = await store.syncThread(thread);
201
+ res.status(201).json(result);
202
+ }
203
+ catch (e) {
204
+ err(res, e);
205
+ }
206
+ });
207
+ r.get('/projects/:id/threads', async (req, res) => {
208
+ try {
209
+ const result = await store.listOpenThreads(req.params['id']);
210
+ res.json(result);
211
+ }
212
+ catch (e) {
213
+ err(res, e);
214
+ }
215
+ });
216
+ r.get('/branches/:branchId/threads', async (req, res) => {
217
+ try {
218
+ const result = await store.listOpenThreadsByBranch(req.params['branchId']);
219
+ res.json(result);
220
+ }
221
+ catch (e) {
222
+ err(res, e);
223
+ }
224
+ });
225
+ // ── Embeddings & Search ───────────────────────────────────────────────────
226
+ r.post('/commits/:id/embedding', async (req, res) => {
227
+ try {
228
+ const { vector } = req.body;
229
+ await store.indexEmbedding(req.params['id'], new Float32Array(vector));
230
+ res.status(204).end();
231
+ }
232
+ catch (e) {
233
+ err(res, e);
234
+ }
235
+ });
236
+ r.post('/projects/:id/search/semantic', async (req, res) => {
237
+ try {
238
+ const { vector, limit } = req.body;
239
+ const result = await store.semanticSearch(new Float32Array(vector), req.params['id'], limit ?? 5);
240
+ res.json(result);
241
+ }
242
+ catch (e) {
243
+ err(res, e);
244
+ }
245
+ });
246
+ r.get('/projects/:id/search', async (req, res) => {
247
+ try {
248
+ const q = req.query['q'];
249
+ if (typeof q !== 'string' || !q.trim()) {
250
+ res.status(400).json({ error: "'q' query param required" });
251
+ return;
252
+ }
253
+ const result = await store.fullTextSearch(q, req.params['id']);
254
+ res.json(result);
255
+ }
256
+ catch (e) {
257
+ err(res, e);
258
+ }
259
+ });
260
+ // ── Agents ────────────────────────────────────────────────────────────────
261
+ r.post('/agents', async (req, res) => {
262
+ try {
263
+ const result = await store.upsertAgent(req.body);
264
+ res.status(201).json(result);
265
+ }
266
+ catch (e) {
267
+ err(res, e);
268
+ }
269
+ });
270
+ r.get('/projects/:id/agents', async (req, res) => {
271
+ try {
272
+ const result = await store.listAgents(req.params['id']);
273
+ res.json(result);
274
+ }
275
+ catch (e) {
276
+ err(res, e);
277
+ }
278
+ });
279
+ return r;
280
+ }
281
+ //# sourceMappingURL=store-router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store-router.js","sourceRoot":"","sources":["../src/store-router.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@contextgit/api",
3
+ "version": "0.0.3",
4
+ "type": "module",
5
+ "main": "./dist/server.js",
6
+ "exports": {
7
+ ".": "./dist/server.js",
8
+ "./bin": "./dist/index.js"
9
+ },
10
+ "files": ["dist"],
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "typecheck": "tsc --noEmit"
14
+ },
15
+ "dependencies": {
16
+ "@contextgit/core": "0.0.3",
17
+ "@contextgit/store": "0.0.3",
18
+ "express": "^4.19.0",
19
+ "simple-git": "^3.27.0"
20
+ },
21
+ "devDependencies": {
22
+ "@types/express": "^4.17.21",
23
+ "@types/node": "^20.0.0",
24
+ "typescript": "^5.4.0"
25
+ }
26
+ }