@gitgov/core 2.1.1 → 2.2.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/README.md CHANGED
@@ -16,6 +16,8 @@ pnpm add @gitgov/core
16
16
 
17
17
  The SDK uses dependency injection. Each adapter receives its dependencies via constructor.
18
18
 
19
+ ### Filesystem Backend (CLI, local development)
20
+
19
21
  ```typescript
20
22
  import { Adapters, Store, EventBus } from '@gitgov/core';
21
23
  import { FsRecordStore } from '@gitgov/core/fs';
@@ -42,6 +44,40 @@ const task = await backlog.createTask(
42
44
  );
43
45
  ```
44
46
 
47
+ ### GitHub API Backend
48
+
49
+ For SaaS, Forge apps, or GitHub Actions — no filesystem needed:
50
+
51
+ ```typescript
52
+ import { Octokit } from '@octokit/rest';
53
+ import {
54
+ GitHubRecordStore,
55
+ GitHubConfigStore,
56
+ GitHubGitModule,
57
+ GitHubFileLister,
58
+ } from '@gitgov/core/github';
59
+ import type { TaskRecord } from '@gitgov/core';
60
+
61
+ const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
62
+ const repoOpts = { owner: 'my-org', repo: 'my-repo', basePath: '.gitgov/tasks' };
63
+
64
+ const taskStore = new GitHubRecordStore<TaskRecord>(repoOpts, octokit);
65
+
66
+ // Read — returns parsed JSON, caches SHA for subsequent writes
67
+ const task = await taskStore.get('task-001');
68
+
69
+ // Write — returns { commitSha } from the created commit
70
+ const result = await taskStore.put('task-002', newTask);
71
+
72
+ // Atomic batch — single commit for N records (requires GitHubGitModule)
73
+ const gitModule = new GitHubGitModule({ owner: 'my-org', repo: 'my-repo' }, octokit);
74
+ const batchStore = new GitHubRecordStore<TaskRecord>(repoOpts, octokit, gitModule);
75
+ await batchStore.putMany([
76
+ { id: 'task-003', value: task3 },
77
+ { id: 'task-004', value: task4 },
78
+ ]);
79
+ ```
80
+
45
81
  ## Architecture
46
82
 
47
83
  ```mermaid
@@ -56,13 +92,20 @@ graph LR
56
92
  Modules --> Records
57
93
  end
58
94
 
59
- subgraph "@gitgov/core/fs — I/O"
95
+ subgraph "@gitgov/core/fs — Local I/O"
60
96
  FsStore["FsRecordStore"]
61
97
  FsGit["LocalGitModule"]
62
98
  FsLint["FsLintModule"]
63
99
  FsOther["FsKeyProvider, FsFileLister, ..."]
64
100
  end
65
101
 
102
+ subgraph "@gitgov/core/github — GitHub API"
103
+ GhStore["GitHubRecordStore"]
104
+ GhGit["GitHubGitModule"]
105
+ GhConfig["GitHubConfigStore"]
106
+ GhFiles["GitHubFileLister"]
107
+ end
108
+
66
109
  subgraph "@gitgov/core/memory — Testing"
67
110
  MemStore["MemoryRecordStore"]
68
111
  MemGit["MemoryGitModule"]
@@ -70,25 +113,29 @@ graph LR
70
113
  end
71
114
 
72
115
  Adapters -.->|DI| FsStore
116
+ Adapters -.->|DI| GhStore
73
117
  Adapters -.->|DI| MemStore
74
118
 
75
119
  CLI["@gitgov/cli"] --> Adapters
76
120
  SaaS["@gitgov/saas-api"] --> Adapters
121
+ Forge["Forge Apps"] --> Adapters
77
122
 
78
123
  style Adapters fill:#e8f5e8,stroke:#4caf50,stroke-width:2px
79
124
  style FsStore fill:#e3f2fd,stroke:#1976d2
125
+ style GhStore fill:#f3e5f5,stroke:#7b1fa2
80
126
  style MemStore fill:#fff3e0,stroke:#f57c00
81
127
  ```
82
128
 
83
- ### 3 Export Paths
129
+ ### 4 Export Paths
84
130
 
85
131
  | Import | Contents | I/O |
86
132
  |--------|----------|-----|
87
133
  | `@gitgov/core` | Interfaces, types, pure logic, factories, validators | No |
88
- | `@gitgov/core/fs` | Filesystem implementations (FsRecordStore, LocalGitModule, FsLintModule, ...) | Yes |
134
+ | `@gitgov/core/fs` | Filesystem implementations (FsRecordStore, LocalGitModule, FsLintModule, ...) | Local |
135
+ | `@gitgov/core/github` | GitHub API implementations (GitHubRecordStore, GitHubGitModule, GitHubConfigStore, GitHubFileLister) | Remote |
89
136
  | `@gitgov/core/memory` | In-memory implementations for testing (MemoryRecordStore, MemoryGitModule, ...) | No |
90
137
 
91
- The root import (`@gitgov/core`) never imports `fs`, `path`, or `child_process`.
138
+ The root import (`@gitgov/core`) never imports `fs`, `path`, `child_process`, or `@octokit/rest`.
92
139
 
93
140
  ### Record Symmetry
94
141
 
@@ -128,8 +175,8 @@ Adapters are orchestrators that compose modules. All receive dependencies via co
128
175
  | `record_factories/` | Factories with defaults for creating records |
129
176
  | `record_validations/` | Business validators (above schema) |
130
177
  | `record_schemas/` | JSON Schemas + schema cache + errors |
131
- | `record_store/` | `RecordStore<T>` interface (impl in fs/memory) |
132
- | `config_store/` | Storage for project config.json |
178
+ | `record_store/` | `RecordStore<V, R, O>` interface (impl in fs/memory/github) |
179
+ | `config_store/` | Storage for project config.json (impl in fs/github) |
133
180
  | `config_manager/` | Typed access to config.json (versioned in git) |
134
181
  | `session_store/` | Storage for .session.json |
135
182
  | `session_manager/` | Typed access to .session.json (ephemeral, not versioned) |
@@ -1,4 +1,5 @@
1
- import { m as IConfigManager, C as ConfigStore, G as GitGovConfig, n as SyncConfig, o as SyncDefaults, k as AuditState, l as AuditStateUpdate, h as ISessionManager, S as SessionStore, a as GitGovSession, A as ActorState, i as SyncPreferencesUpdate, K as KeyProvider, s as FileLister, F as FsFileListerOptions, r as FileListOptions, t as FileStats, R as RecordStore, I as IGitModule } from './index--ahcnsG3.js';
1
+ import { I as ISessionManager, S as SessionStore, G as GitGovSession, A as ActorState, a as SyncPreferencesUpdate, K as KeyProvider } from './key_provider-CRpHFGjN.js';
2
+ import { l as IConfigManager, C as ConfigStore, G as GitGovConfig, S as SyncConfig, m as SyncDefaults, A as AuditState, k as AuditStateUpdate, h as FileLister, F as FsFileListerOptions, i as FileListOptions, j as FileStats, R as RecordStore, a as IGitModule } from './index-D1RVufxB.js';
2
3
 
3
4
  /**
4
5
  * ConfigManager - Project Configuration Manager
package/dist/src/fs.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- import { R as RecordStore, C as ConfigStore, G as GitGovConfig, S as SessionStore, a as GitGovSession, I as IGitModule, b as GitModuleDependencies, E as ExecOptions, c as ExecResult, d as ChangedFile, e as GetCommitHistoryOptions, f as CommitInfo, g as CommitAuthor } from './index--ahcnsG3.js';
2
- export { F as FsFileListerOptions } from './index--ahcnsG3.js';
3
- import { C as ConfigManager, S as SessionManager, I as ILintModule, L as LintOptions, a as LintReport, F as FixRecordOptions, b as FixReport, R as RecordStores, c as IIndexerAdapter, G as GitGovRecord, d as LintRecordContext, e as LintResult, f as IProjectInitializer, E as EnvironmentValidation, g as ISyncStateModule, h as SyncStateModuleDependencies, i as StateDeltaFile, j as ConflictDiff, k as IntegrityViolation, A as AuditStateOptions, l as AuditStateReport, m as SyncStatePushOptions, n as SyncStatePushResult, o as SyncStatePullOptions, p as SyncStatePullResult, q as SyncStateResolveOptions, r as SyncStateResolveResult, s as IEventStream, t as IAgentRunner, P as ProtocolHandlerRegistry, u as AgentRunnerDependencies, v as RunOptions, w as AgentResponse } from './agent_runner-ByOUWOt6.js';
4
- export { z as FsFileLister, x as FsKeyProvider, y as FsKeyProviderOptions } from './agent_runner-ByOUWOt6.js';
1
+ import { R as RecordStore, I as IdEncoder, C as ConfigStore, G as GitGovConfig, a as IGitModule, b as GitModuleDependencies, E as ExecOptions, c as ExecResult, d as ChangedFile, e as GetCommitHistoryOptions, f as CommitInfo, g as CommitAuthor } from './index-D1RVufxB.js';
2
+ export { D as DEFAULT_ID_ENCODER, F as FsFileListerOptions } from './index-D1RVufxB.js';
3
+ import { C as ConfigManager, S as SessionManager, I as ILintModule, L as LintOptions, a as LintReport, F as FixRecordOptions, b as FixReport, R as RecordStores, c as IIndexerAdapter, G as GitGovRecord, d as LintRecordContext, e as LintResult, f as IProjectInitializer, E as EnvironmentValidation, g as ISyncStateModule, h as SyncStateModuleDependencies, i as StateDeltaFile, j as ConflictDiff, k as IntegrityViolation, A as AuditStateOptions, l as AuditStateReport, m as SyncStatePushOptions, n as SyncStatePushResult, o as SyncStatePullOptions, p as SyncStatePullResult, q as SyncStateResolveOptions, r as SyncStateResolveResult, s as IEventStream, t as IAgentRunner, P as ProtocolHandlerRegistry, u as AgentRunnerDependencies, v as RunOptions, w as AgentResponse } from './agent_runner-Cs5HXt4h.js';
4
+ export { z as FsFileLister, x as FsKeyProvider, y as FsKeyProviderOptions } from './agent_runner-Cs5HXt4h.js';
5
+ import { S as SessionStore, G as GitGovSession } from './key_provider-CRpHFGjN.js';
5
6
 
6
7
  /**
7
8
  * Serializer for FsRecordStore - allows custom serialization
@@ -10,21 +11,6 @@ interface Serializer {
10
11
  stringify: (value: unknown) => string;
11
12
  parse: <T>(text: string) => T;
12
13
  }
13
- /**
14
- * IdEncoder for transforming IDs to filesystem-safe filenames
15
- * Useful for characters not allowed in filesystem (e.g., `:` on Windows)
16
- */
17
- interface IdEncoder {
18
- /** Transform ID to filename-safe string */
19
- encode: (id: string) => string;
20
- /** Recover original ID from filename */
21
- decode: (encoded: string) => string;
22
- }
23
- /**
24
- * Default encoder: `:` → `_` (for IDs like "human:camilo")
25
- * Reversible because IDs cannot contain `_` (see id_generator.ts)
26
- */
27
- declare const DEFAULT_ID_ENCODER: IdEncoder;
28
14
  /**
29
15
  * Options for FsRecordStore
30
16
  */
@@ -63,6 +49,10 @@ declare class FsRecordStore<T> implements RecordStore<T> {
63
49
  private getFilePath;
64
50
  get(id: string): Promise<T | null>;
65
51
  put(id: string, value: T): Promise<void>;
52
+ putMany(entries: Array<{
53
+ id: string;
54
+ value: T;
55
+ }>): Promise<void>;
66
56
  delete(id: string): Promise<void>;
67
57
  list(): Promise<string[]>;
68
58
  exists(id: string): Promise<boolean>;
@@ -920,6 +910,7 @@ declare class LocalGitModule implements IGitModule {
920
910
  */
921
911
  add(filePaths: string[], options?: {
922
912
  force?: boolean;
913
+ contentMap?: Record<string, string>;
923
914
  }): Promise<void>;
924
915
  /**
925
916
  * Removes files from both working directory and staging area
@@ -1366,4 +1357,4 @@ declare class FsAgentRunner implements IAgentRunner {
1366
1357
  */
1367
1358
  declare function createAgentRunner(deps: AgentRunnerDependencies): IAgentRunner;
1368
1359
 
1369
- export { DEFAULT_ID_ENCODER, type FileSystem, FsAgentRunner, AgentRunnerDependencies as FsAgentRunnerDependencies, FsConfigStore, type FsFixOptions, FsLintModule, type FsLintModuleDependencies, type FsLintOptions, FsProjectInitializer, FsRecordStore, FsSessionStore, FsSyncStateModule, FsWatcherStateModule, LocalGitModule as GitModule, GitModuleDependencies, type IFsLintModule, IGitModule, LocalGitModule, createAgentRunner, createConfigManager, createSessionManager, findGitgovRoot, findProjectRoot, getGitgovPath, isGitgovProject, resetDiscoveryCache };
1360
+ export { type FileSystem, FsAgentRunner, AgentRunnerDependencies as FsAgentRunnerDependencies, FsConfigStore, type FsFixOptions, FsLintModule, type FsLintModuleDependencies, type FsLintOptions, FsProjectInitializer, FsRecordStore, FsSessionStore, FsSyncStateModule, FsWatcherStateModule, LocalGitModule as GitModule, GitModuleDependencies, type IFsLintModule, IGitModule, LocalGitModule, createAgentRunner, createConfigManager, createSessionManager, findGitgovRoot, findProjectRoot, getGitgovPath, isGitgovProject, resetDiscoveryCache };
package/dist/src/fs.js CHANGED
@@ -16,10 +16,14 @@ import os from 'os';
16
16
  import chokidar from 'chokidar';
17
17
 
18
18
  // src/record_store/fs/fs_record_store.ts
19
+
20
+ // src/record_store/record_store.ts
19
21
  var DEFAULT_ID_ENCODER = {
20
22
  encode: (id) => id.replace(/:/g, "_"),
21
23
  decode: (encoded) => encoded.replace(/_/g, ":")
22
24
  };
25
+
26
+ // src/record_store/fs/fs_record_store.ts
23
27
  var DEFAULT_SERIALIZER = {
24
28
  stringify: (value) => JSON.stringify(value, null, 2),
25
29
  parse: (text) => JSON.parse(text)
@@ -70,6 +74,11 @@ var FsRecordStore = class {
70
74
  const content = this.serializer.stringify(value);
71
75
  await fs.writeFile(filePath, content, "utf-8");
72
76
  }
77
+ async putMany(entries) {
78
+ for (const { id, value } of entries) {
79
+ await this.put(id, value);
80
+ }
81
+ }
73
82
  async delete(id) {
74
83
  const filePath = this.getFilePath(id);
75
84
  try {