@indigoai-us/hq-cli 5.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.
Files changed (102) hide show
  1. package/dist/__tests__/credentials.test.d.ts +5 -0
  2. package/dist/__tests__/credentials.test.d.ts.map +1 -0
  3. package/dist/__tests__/credentials.test.js +169 -0
  4. package/dist/__tests__/credentials.test.js.map +1 -0
  5. package/dist/commands/add.d.ts +6 -0
  6. package/dist/commands/add.d.ts.map +1 -0
  7. package/dist/commands/add.js +60 -0
  8. package/dist/commands/add.js.map +1 -0
  9. package/dist/commands/auth.d.ts +17 -0
  10. package/dist/commands/auth.d.ts.map +1 -0
  11. package/dist/commands/auth.js +269 -0
  12. package/dist/commands/auth.js.map +1 -0
  13. package/dist/commands/cloud-setup.d.ts +19 -0
  14. package/dist/commands/cloud-setup.d.ts.map +1 -0
  15. package/dist/commands/cloud-setup.js +206 -0
  16. package/dist/commands/cloud-setup.js.map +1 -0
  17. package/dist/commands/cloud.d.ts +16 -0
  18. package/dist/commands/cloud.d.ts.map +1 -0
  19. package/dist/commands/cloud.js +263 -0
  20. package/dist/commands/cloud.js.map +1 -0
  21. package/dist/commands/initial-upload.d.ts +67 -0
  22. package/dist/commands/initial-upload.d.ts.map +1 -0
  23. package/dist/commands/initial-upload.js +205 -0
  24. package/dist/commands/initial-upload.js.map +1 -0
  25. package/dist/commands/list.d.ts +6 -0
  26. package/dist/commands/list.d.ts.map +1 -0
  27. package/dist/commands/list.js +55 -0
  28. package/dist/commands/list.js.map +1 -0
  29. package/dist/commands/sync.d.ts +6 -0
  30. package/dist/commands/sync.d.ts.map +1 -0
  31. package/dist/commands/sync.js +104 -0
  32. package/dist/commands/sync.js.map +1 -0
  33. package/dist/commands/update.d.ts +7 -0
  34. package/dist/commands/update.d.ts.map +1 -0
  35. package/dist/commands/update.js +60 -0
  36. package/dist/commands/update.js.map +1 -0
  37. package/dist/index.d.ts +6 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +36 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/strategies/link.d.ts +7 -0
  42. package/dist/strategies/link.d.ts.map +1 -0
  43. package/dist/strategies/link.js +51 -0
  44. package/dist/strategies/link.js.map +1 -0
  45. package/dist/strategies/merge.d.ts +7 -0
  46. package/dist/strategies/merge.d.ts.map +1 -0
  47. package/dist/strategies/merge.js +110 -0
  48. package/dist/strategies/merge.js.map +1 -0
  49. package/dist/sync-worker.d.ts +11 -0
  50. package/dist/sync-worker.d.ts.map +1 -0
  51. package/dist/sync-worker.js +77 -0
  52. package/dist/sync-worker.js.map +1 -0
  53. package/dist/types.d.ts +41 -0
  54. package/dist/types.d.ts.map +1 -0
  55. package/dist/types.js +5 -0
  56. package/dist/types.js.map +1 -0
  57. package/dist/utils/api-client.d.ts +26 -0
  58. package/dist/utils/api-client.d.ts.map +1 -0
  59. package/dist/utils/api-client.js +87 -0
  60. package/dist/utils/api-client.js.map +1 -0
  61. package/dist/utils/credentials.d.ts +44 -0
  62. package/dist/utils/credentials.d.ts.map +1 -0
  63. package/dist/utils/credentials.js +101 -0
  64. package/dist/utils/credentials.js.map +1 -0
  65. package/dist/utils/git.d.ts +13 -0
  66. package/dist/utils/git.d.ts.map +1 -0
  67. package/dist/utils/git.js +70 -0
  68. package/dist/utils/git.js.map +1 -0
  69. package/dist/utils/manifest.d.ts +16 -0
  70. package/dist/utils/manifest.d.ts.map +1 -0
  71. package/dist/utils/manifest.js +95 -0
  72. package/dist/utils/manifest.js.map +1 -0
  73. package/dist/utils/sync.d.ts +125 -0
  74. package/dist/utils/sync.d.ts.map +1 -0
  75. package/dist/utils/sync.js +291 -0
  76. package/dist/utils/sync.js.map +1 -0
  77. package/package.json +36 -0
  78. package/src/__tests__/cloud-setup.test.ts +117 -0
  79. package/src/__tests__/credentials.test.ts +203 -0
  80. package/src/__tests__/initial-upload.test.ts +414 -0
  81. package/src/__tests__/sync.test.ts +627 -0
  82. package/src/commands/add.ts +74 -0
  83. package/src/commands/auth.ts +303 -0
  84. package/src/commands/cloud-setup.ts +251 -0
  85. package/src/commands/cloud.ts +300 -0
  86. package/src/commands/initial-upload.ts +263 -0
  87. package/src/commands/list.ts +66 -0
  88. package/src/commands/sync.ts +149 -0
  89. package/src/commands/update.ts +71 -0
  90. package/src/hq-cloud.d.ts +19 -0
  91. package/src/index.ts +46 -0
  92. package/src/strategies/link.ts +62 -0
  93. package/src/strategies/merge.ts +142 -0
  94. package/src/sync-worker.ts +82 -0
  95. package/src/types.ts +47 -0
  96. package/src/utils/api-client.ts +111 -0
  97. package/src/utils/credentials.ts +124 -0
  98. package/src/utils/git.ts +74 -0
  99. package/src/utils/manifest.ts +111 -0
  100. package/src/utils/sync.ts +381 -0
  101. package/tsconfig.json +9 -0
  102. package/vitest.config.ts +8 -0
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Merge Sync Strategy (US-007)
3
+ * Copies files from module into HQ, tracks state for conflict detection
4
+ */
5
+ import * as fs from 'fs';
6
+ import * as path from 'path';
7
+ import * as crypto from 'crypto';
8
+ import { readState, writeState } from '../utils/manifest.js';
9
+ function hashFile(filePath) {
10
+ const content = fs.readFileSync(filePath);
11
+ return crypto.createHash('sha256').update(content).digest('hex');
12
+ }
13
+ function copyRecursive(srcDir, destDir, state, moduleName, hqRoot, filesChanged) {
14
+ if (!fs.existsSync(destDir)) {
15
+ fs.mkdirSync(destDir, { recursive: true });
16
+ }
17
+ const entries = fs.readdirSync(srcDir, { withFileTypes: true });
18
+ for (const entry of entries) {
19
+ const srcPath = path.join(srcDir, entry.name);
20
+ const destPath = path.join(destDir, entry.name);
21
+ if (entry.isDirectory()) {
22
+ copyRecursive(srcPath, destPath, state, moduleName, hqRoot, filesChanged);
23
+ }
24
+ else {
25
+ const relativeDest = path.relative(hqRoot, destPath).replace(/\\/g, '/');
26
+ const newHash = hashFile(srcPath);
27
+ // Check if file exists and has been modified by user
28
+ if (fs.existsSync(destPath)) {
29
+ const existingHash = hashFile(destPath);
30
+ const lastSyncedHash = state.files[relativeDest]?.hash;
31
+ if (lastSyncedHash && existingHash !== lastSyncedHash && existingHash !== newHash) {
32
+ // User modified the file since last sync - skip (conflict)
33
+ console.warn(` Conflict: ${relativeDest} has local changes, skipping`);
34
+ continue;
35
+ }
36
+ if (existingHash === newHash) {
37
+ // File unchanged, skip
38
+ continue;
39
+ }
40
+ }
41
+ // Copy file
42
+ fs.copyFileSync(srcPath, destPath);
43
+ filesChanged.count++;
44
+ // Track in state
45
+ state.files[relativeDest] = {
46
+ hash: newHash,
47
+ syncedAt: new Date().toISOString(),
48
+ fromModule: moduleName,
49
+ };
50
+ }
51
+ }
52
+ }
53
+ export async function mergeSync(module, moduleDir, hqRoot) {
54
+ let state = readState(hqRoot);
55
+ if (!state) {
56
+ state = { version: '1', files: {} };
57
+ }
58
+ const filesChanged = { count: 0 };
59
+ for (const mapping of module.paths) {
60
+ const srcPath = path.join(moduleDir, mapping.src);
61
+ const destPath = path.join(hqRoot, mapping.dest);
62
+ if (!fs.existsSync(srcPath)) {
63
+ return {
64
+ module: module.name,
65
+ success: false,
66
+ action: 'skipped',
67
+ message: `Source path not found: ${mapping.src}`,
68
+ };
69
+ }
70
+ const srcStat = fs.statSync(srcPath);
71
+ if (srcStat.isDirectory()) {
72
+ copyRecursive(srcPath, destPath, state, module.name, hqRoot, filesChanged);
73
+ }
74
+ else {
75
+ // Single file
76
+ const destDir = path.dirname(destPath);
77
+ if (!fs.existsSync(destDir)) {
78
+ fs.mkdirSync(destDir, { recursive: true });
79
+ }
80
+ const relativeDest = path.relative(hqRoot, destPath).replace(/\\/g, '/');
81
+ const newHash = hashFile(srcPath);
82
+ if (fs.existsSync(destPath)) {
83
+ const existingHash = hashFile(destPath);
84
+ const lastSyncedHash = state.files[relativeDest]?.hash;
85
+ if (lastSyncedHash && existingHash !== lastSyncedHash && existingHash !== newHash) {
86
+ console.warn(` Conflict: ${relativeDest} has local changes, skipping`);
87
+ continue;
88
+ }
89
+ if (existingHash === newHash) {
90
+ continue;
91
+ }
92
+ }
93
+ fs.copyFileSync(srcPath, destPath);
94
+ filesChanged.count++;
95
+ state.files[relativeDest] = {
96
+ hash: newHash,
97
+ syncedAt: new Date().toISOString(),
98
+ fromModule: module.name,
99
+ };
100
+ }
101
+ }
102
+ writeState(hqRoot, state);
103
+ return {
104
+ module: module.name,
105
+ success: true,
106
+ action: 'synced',
107
+ filesChanged: filesChanged.count,
108
+ };
109
+ }
110
+ //# sourceMappingURL=merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/strategies/merge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Background sync worker for "hq sync start".
3
+ *
4
+ * Forked as a detached child process. Polls for changes at a configurable
5
+ * interval and runs a full bidirectional sync each cycle.
6
+ *
7
+ * Usage (internal — called by cloud.ts):
8
+ * node sync-worker.js <hqRoot> <intervalMs>
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=sync-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-worker.d.ts","sourceRoot":"","sources":["../src/sync-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Background sync worker for "hq sync start".
3
+ *
4
+ * Forked as a detached child process. Polls for changes at a configurable
5
+ * interval and runs a full bidirectional sync each cycle.
6
+ *
7
+ * Usage (internal — called by cloud.ts):
8
+ * node sync-worker.js <hqRoot> <intervalMs>
9
+ */
10
+ import { fullSync, readSyncState, writeSyncState, computeLocalManifest } from './utils/sync.js';
11
+ const hqRoot = process.argv[2];
12
+ const intervalMs = parseInt(process.argv[3] ?? '30000', 10);
13
+ if (!hqRoot) {
14
+ process.exit(1);
15
+ }
16
+ /** Run one sync cycle. */
17
+ async function syncCycle() {
18
+ try {
19
+ const result = await fullSync(hqRoot);
20
+ // Update state
21
+ const manifest = computeLocalManifest(hqRoot);
22
+ const state = readSyncState(hqRoot);
23
+ state.running = true;
24
+ state.pid = process.pid;
25
+ state.lastSync = new Date().toISOString();
26
+ state.fileCount = manifest.length;
27
+ state.errors = result.errors;
28
+ writeSyncState(hqRoot, state);
29
+ }
30
+ catch {
31
+ // Log errors to state, but keep running
32
+ try {
33
+ const state = readSyncState(hqRoot);
34
+ state.errors = ['Sync cycle failed — will retry next interval'];
35
+ writeSyncState(hqRoot, state);
36
+ }
37
+ catch {
38
+ // Can't even write state — just continue
39
+ }
40
+ }
41
+ }
42
+ /** Main loop. */
43
+ async function run() {
44
+ // Handle graceful shutdown
45
+ process.on('SIGTERM', () => {
46
+ try {
47
+ const state = readSyncState(hqRoot);
48
+ state.running = false;
49
+ state.pid = undefined;
50
+ writeSyncState(hqRoot, state);
51
+ }
52
+ catch {
53
+ // Best-effort cleanup
54
+ }
55
+ process.exit(0);
56
+ });
57
+ process.on('SIGINT', () => {
58
+ try {
59
+ const state = readSyncState(hqRoot);
60
+ state.running = false;
61
+ state.pid = undefined;
62
+ writeSyncState(hqRoot, state);
63
+ }
64
+ catch {
65
+ // Best-effort cleanup
66
+ }
67
+ process.exit(0);
68
+ });
69
+ // Run first sync immediately
70
+ await syncCycle();
71
+ // Then poll at the configured interval
72
+ setInterval(() => {
73
+ void syncCycle();
74
+ }, intervalMs);
75
+ }
76
+ void run();
77
+ //# sourceMappingURL=sync-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-worker.js","sourceRoot":"","sources":["../src/sync-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEhG,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC/B,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,EAAE,CAAC,CAAC;AAE5D,IAAI,CAAC,MAAM,EAAE,CAAC;IACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,0BAA0B;AAC1B,KAAK,UAAU,SAAS;IACtB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;QAEtC,eAAe;QACf,MAAM,QAAQ,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;QACpC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;QACrB,KAAK,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACxB,KAAK,CAAC,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC1C,KAAK,CAAC,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC;QAClC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC7B,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,wCAAwC;QACxC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;YACpC,KAAK,CAAC,MAAM,GAAG,CAAC,8CAA8C,CAAC,CAAC;YAChE,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,yCAAyC;QAC3C,CAAC;IACH,CAAC;AACH,CAAC;AAED,iBAAiB;AACjB,KAAK,UAAU,GAAG;IAChB,2BAA2B;IAC3B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;QACzB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;YACpC,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC;YACtB,KAAK,CAAC,GAAG,GAAG,SAAS,CAAC;YACtB,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,sBAAsB;QACxB,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACxB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;YACpC,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC;YACtB,KAAK,CAAC,GAAG,GAAG,SAAS,CAAC;YACtB,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,sBAAsB;QACxB,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,6BAA6B;IAC7B,MAAM,SAAS,EAAE,CAAC;IAElB,uCAAuC;IACvC,WAAW,CAAC,GAAG,EAAE;QACf,KAAK,SAAS,EAAE,CAAC;IACnB,CAAC,EAAE,UAAU,CAAC,CAAC;AACjB,CAAC;AAED,KAAK,GAAG,EAAE,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * HQ Module Manifest Types (US-001)
3
+ */
4
+ export type SyncStrategy = 'link' | 'merge' | 'copy';
5
+ export type AccessLevel = 'public' | 'team' | `role:${string}`;
6
+ export interface PathMapping {
7
+ src: string;
8
+ dest: string;
9
+ }
10
+ export interface ModuleDefinition {
11
+ name: string;
12
+ repo: string;
13
+ branch?: string;
14
+ strategy: SyncStrategy;
15
+ paths: PathMapping[];
16
+ access?: AccessLevel;
17
+ }
18
+ export interface ModulesManifest {
19
+ version: '1';
20
+ modules: ModuleDefinition[];
21
+ }
22
+ export interface ModuleLock {
23
+ version: '1';
24
+ locked: Record<string, string>;
25
+ }
26
+ export interface SyncState {
27
+ version: '1';
28
+ files: Record<string, {
29
+ hash: string;
30
+ syncedAt: string;
31
+ fromModule: string;
32
+ }>;
33
+ }
34
+ export interface SyncResult {
35
+ module: string;
36
+ success: boolean;
37
+ action: 'cloned' | 'fetched' | 'synced' | 'skipped';
38
+ message?: string;
39
+ filesChanged?: number;
40
+ }
41
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AACrD,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,MAAM,EAAE,CAAC;AAE/D,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,GAAG,CAAC;IACb,OAAO,EAAE,gBAAgB,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,GAAG,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,GAAG,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * HQ Module Manifest Types (US-001)
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * API client for hq-cloud.
3
+ * Reads stored credentials and attaches Authorization header to all requests.
4
+ *
5
+ * Base URL resolution order:
6
+ * 1. HQ_CLOUD_API_URL environment variable
7
+ * 2. ~/.hq/config.json "apiUrl" field
8
+ * 3. Default production URL
9
+ */
10
+ /**
11
+ * Resolve the hq-cloud API base URL.
12
+ */
13
+ export declare function getApiUrl(): string;
14
+ /** Standard response shape from the API */
15
+ export interface ApiResponse<T = unknown> {
16
+ ok: boolean;
17
+ status: number;
18
+ data?: T;
19
+ error?: string;
20
+ }
21
+ /**
22
+ * Make an authenticated request to the hq-cloud API.
23
+ * Throws if not logged in. Returns parsed JSON response.
24
+ */
25
+ export declare function apiRequest<T = unknown>(method: string, urlPath: string, body?: unknown): Promise<ApiResponse<T>>;
26
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/utils/api-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAaH;;GAEG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAqBlC;AAED,2CAA2C;AAC3C,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,CAAC,GAAG,OAAO,EAC1C,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,OAAO,GACb,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CA+CzB"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * API client for hq-cloud.
3
+ * Reads stored credentials and attaches Authorization header to all requests.
4
+ *
5
+ * Base URL resolution order:
6
+ * 1. HQ_CLOUD_API_URL environment variable
7
+ * 2. ~/.hq/config.json "apiUrl" field
8
+ * 3. Default production URL
9
+ */
10
+ import * as fs from 'fs';
11
+ import * as path from 'path';
12
+ import * as os from 'os';
13
+ import { readCredentials } from './credentials.js';
14
+ /** Default API base URL (production) */
15
+ const DEFAULT_API_URL = 'https://api.hq.indigoai.com';
16
+ /** Path to optional config file */
17
+ const CONFIG_PATH = path.join(os.homedir(), '.hq', 'config.json');
18
+ /**
19
+ * Resolve the hq-cloud API base URL.
20
+ */
21
+ export function getApiUrl() {
22
+ // 1. Environment variable takes precedence
23
+ if (process.env['HQ_CLOUD_API_URL']) {
24
+ return process.env['HQ_CLOUD_API_URL'].replace(/\/+$/, '');
25
+ }
26
+ // 2. Config file
27
+ try {
28
+ if (fs.existsSync(CONFIG_PATH)) {
29
+ const raw = fs.readFileSync(CONFIG_PATH, 'utf-8');
30
+ const config = JSON.parse(raw);
31
+ if (config.apiUrl) {
32
+ return config.apiUrl.replace(/\/+$/, '');
33
+ }
34
+ }
35
+ }
36
+ catch {
37
+ // Ignore config read errors
38
+ }
39
+ // 3. Default
40
+ return DEFAULT_API_URL;
41
+ }
42
+ /**
43
+ * Make an authenticated request to the hq-cloud API.
44
+ * Throws if not logged in. Returns parsed JSON response.
45
+ */
46
+ export async function apiRequest(method, urlPath, body) {
47
+ const creds = readCredentials();
48
+ if (!creds) {
49
+ throw new Error('Not logged in. Run "hq auth login" first.');
50
+ }
51
+ const baseUrl = getApiUrl();
52
+ const url = `${baseUrl}${urlPath.startsWith('/') ? urlPath : '/' + urlPath}`;
53
+ const headers = {
54
+ 'Authorization': `Bearer ${creds.token}`,
55
+ 'Content-Type': 'application/json',
56
+ };
57
+ const fetchOptions = {
58
+ method,
59
+ headers,
60
+ };
61
+ if (body !== undefined && method !== 'GET') {
62
+ fetchOptions.body = JSON.stringify(body);
63
+ }
64
+ const response = await fetch(url, fetchOptions);
65
+ let data;
66
+ try {
67
+ data = await response.json();
68
+ }
69
+ catch {
70
+ // Response may not be JSON
71
+ }
72
+ if (!response.ok) {
73
+ return {
74
+ ok: false,
75
+ status: response.status,
76
+ error: data?.message
77
+ ?? data?.error
78
+ ?? `HTTP ${response.status}`,
79
+ };
80
+ }
81
+ return {
82
+ ok: true,
83
+ status: response.status,
84
+ data,
85
+ };
86
+ }
87
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/utils/api-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,wCAAwC;AACxC,MAAM,eAAe,GAAG,6BAA6B,CAAC;AAEtD,mCAAmC;AACnC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;AAElE;;GAEG;AACH,MAAM,UAAU,SAAS;IACvB,2CAA2C;IAC3C,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACpC,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,iBAAiB;IACjB,IAAI,CAAC;QACH,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/B,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YAClD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAwB,CAAC;YACtD,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClB,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,4BAA4B;IAC9B,CAAC;IAED,aAAa;IACb,OAAO,eAAe,CAAC;AACzB,CAAC;AAUD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAc,EACd,OAAe,EACf,IAAc;IAEd,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAC5B,MAAM,GAAG,GAAG,GAAG,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,OAAO,EAAE,CAAC;IAE7E,MAAM,OAAO,GAA2B;QACtC,eAAe,EAAE,UAAU,KAAK,CAAC,KAAK,EAAE;QACxC,cAAc,EAAE,kBAAkB;KACnC,CAAC;IAEF,MAAM,YAAY,GAAgB;QAChC,MAAM;QACN,OAAO;KACR,CAAC;IAEF,IAAI,IAAI,KAAK,SAAS,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;QAC3C,YAAY,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAEhD,IAAI,IAAmB,CAAC;IACxB,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAO,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,2BAA2B;IAC7B,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,KAAK,EAAG,IAA2C,EAAE,OAAO;mBACtD,IAA2C,EAAE,KAAK;mBACnD,QAAQ,QAAQ,CAAC,MAAM,EAAE;SAC/B,CAAC;IACJ,CAAC;IAED,OAAO;QACL,EAAE,EAAE,IAAI;QACR,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,IAAI;KACL,CAAC;AACJ,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Credential storage for HQ CLI authentication.
3
+ * Stores Clerk auth tokens in ~/.hq/credentials.json.
4
+ */
5
+ /** Stored credential shape */
6
+ export interface HqCredentials {
7
+ /** Clerk session token (JWT) */
8
+ token: string;
9
+ /** Clerk user ID */
10
+ userId: string;
11
+ /** User's email (for display) */
12
+ email?: string;
13
+ /** When the token was stored (ISO string) */
14
+ storedAt: string;
15
+ /** When the token expires (ISO string, if known) */
16
+ expiresAt?: string;
17
+ }
18
+ /**
19
+ * Set the base directory for config files. Intended for testing only.
20
+ */
21
+ export declare function _setConfigHome(dir: string | null): void;
22
+ /**
23
+ * Read stored credentials. Returns null if not logged in or file is missing/corrupt.
24
+ */
25
+ export declare function readCredentials(): HqCredentials | null;
26
+ /**
27
+ * Write credentials to disk. Creates ~/.hq if needed.
28
+ * File permissions are set to owner-only (0o600).
29
+ */
30
+ export declare function writeCredentials(creds: HqCredentials): void;
31
+ /**
32
+ * Clear stored credentials (logout).
33
+ * Returns true if credentials were removed, false if none existed.
34
+ */
35
+ export declare function clearCredentials(): boolean;
36
+ /**
37
+ * Get the credentials file path (for display/debugging).
38
+ */
39
+ export declare function getCredentialsPath(): string;
40
+ /**
41
+ * Check if credentials are expired (if expiresAt is set).
42
+ */
43
+ export declare function isExpired(creds: HqCredentials): boolean;
44
+ //# sourceMappingURL=credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/utils/credentials.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,8BAA8B;AAC9B,MAAM,WAAW,aAAa;IAC5B,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AASD;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAEvD;AA8BD;;GAEG;AACH,wBAAgB,eAAe,IAAI,aAAa,GAAG,IAAI,CAetD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAI3D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAO1C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAKvD"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Credential storage for HQ CLI authentication.
3
+ * Stores Clerk auth tokens in ~/.hq/credentials.json.
4
+ */
5
+ import * as fs from 'fs';
6
+ import * as path from 'path';
7
+ import * as os from 'os';
8
+ /**
9
+ * Override for the config directory base path.
10
+ * Set via HQ_CONFIG_HOME env var or _setConfigHome (for testing).
11
+ * When null, defaults to os.homedir().
12
+ */
13
+ let configHomeOverride = null;
14
+ /**
15
+ * Set the base directory for config files. Intended for testing only.
16
+ */
17
+ export function _setConfigHome(dir) {
18
+ configHomeOverride = dir;
19
+ }
20
+ /**
21
+ * Get the ~/.hq config directory path.
22
+ * Respects HQ_CONFIG_HOME env var, _setConfigHome override, or defaults to ~/.hq.
23
+ */
24
+ function getConfigDir() {
25
+ const base = configHomeOverride
26
+ ?? process.env['HQ_CONFIG_HOME']
27
+ ?? os.homedir();
28
+ return path.join(base, '.hq');
29
+ }
30
+ /**
31
+ * Get the credentials file path.
32
+ */
33
+ function getCredentialsFilePath() {
34
+ return path.join(getConfigDir(), 'credentials.json');
35
+ }
36
+ /**
37
+ * Ensure the config directory exists with restricted permissions.
38
+ */
39
+ function ensureConfigDir() {
40
+ const dir = getConfigDir();
41
+ if (!fs.existsSync(dir)) {
42
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
43
+ }
44
+ }
45
+ /**
46
+ * Read stored credentials. Returns null if not logged in or file is missing/corrupt.
47
+ */
48
+ export function readCredentials() {
49
+ try {
50
+ const credPath = getCredentialsFilePath();
51
+ if (!fs.existsSync(credPath)) {
52
+ return null;
53
+ }
54
+ const raw = fs.readFileSync(credPath, 'utf-8');
55
+ const creds = JSON.parse(raw);
56
+ if (!creds.token || !creds.userId) {
57
+ return null;
58
+ }
59
+ return creds;
60
+ }
61
+ catch {
62
+ return null;
63
+ }
64
+ }
65
+ /**
66
+ * Write credentials to disk. Creates ~/.hq if needed.
67
+ * File permissions are set to owner-only (0o600).
68
+ */
69
+ export function writeCredentials(creds) {
70
+ ensureConfigDir();
71
+ const content = JSON.stringify(creds, null, 2);
72
+ fs.writeFileSync(getCredentialsFilePath(), content, { mode: 0o600 });
73
+ }
74
+ /**
75
+ * Clear stored credentials (logout).
76
+ * Returns true if credentials were removed, false if none existed.
77
+ */
78
+ export function clearCredentials() {
79
+ const credPath = getCredentialsFilePath();
80
+ if (!fs.existsSync(credPath)) {
81
+ return false;
82
+ }
83
+ fs.unlinkSync(credPath);
84
+ return true;
85
+ }
86
+ /**
87
+ * Get the credentials file path (for display/debugging).
88
+ */
89
+ export function getCredentialsPath() {
90
+ return getCredentialsFilePath();
91
+ }
92
+ /**
93
+ * Check if credentials are expired (if expiresAt is set).
94
+ */
95
+ export function isExpired(creds) {
96
+ if (!creds.expiresAt) {
97
+ return false;
98
+ }
99
+ return new Date(creds.expiresAt) <= new Date();
100
+ }
101
+ //# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/utils/credentials.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAgBzB;;;;GAIG;AACH,IAAI,kBAAkB,GAAkB,IAAI,CAAC;AAE7C;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,GAAkB;IAC/C,kBAAkB,GAAG,GAAG,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY;IACnB,MAAM,IAAI,GAAG,kBAAkB;WAC1B,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;WAC7B,EAAE,CAAC,OAAO,EAAE,CAAC;IAClB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,SAAS,sBAAsB;IAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,kBAAkB,CAAC,CAAC;AACvD,CAAC;AAED;;GAEG;AACH,SAAS,eAAe;IACtB,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,sBAAsB,EAAE,CAAC;QAC1C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAkB,CAAC;QAC/C,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAoB;IACnD,eAAe,EAAE,CAAC;IAClB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC/C,EAAE,CAAC,aAAa,CAAC,sBAAsB,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACvE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,QAAQ,GAAG,sBAAsB,EAAE,CAAC;IAC1C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACxB,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,sBAAsB,EAAE,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,KAAoB;IAC5C,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;AACjD,CAAC"}
@@ -0,0 +1,13 @@
1
+ export declare function cloneRepo(repoUrl: string, targetDir: string, branch?: string): Promise<void>;
2
+ export declare function fetchRepo(repoDir: string): Promise<void>;
3
+ export declare function pullRepo(repoDir: string): Promise<void>;
4
+ export declare function getCurrentCommit(repoDir: string): Promise<string>;
5
+ export declare function checkoutCommit(repoDir: string, commitSha: string): Promise<void>;
6
+ export declare function isRepo(dir: string): Promise<boolean>;
7
+ export declare function getRemoteUrl(repoDir: string): Promise<string | null>;
8
+ export declare function isBehindRemote(repoDir: string): Promise<{
9
+ behind: boolean;
10
+ commits: number;
11
+ }>;
12
+ export declare function ensureGitignore(hqRoot: string, entry: string): void;
13
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAIA,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIlG;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9D;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG7D;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIvE;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGtF;AAED,wBAAsB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQ1D;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAS1E;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CASnG;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAUnE"}
@@ -0,0 +1,70 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { simpleGit } from 'simple-git';
4
+ export async function cloneRepo(repoUrl, targetDir, branch) {
5
+ const git = simpleGit();
6
+ const options = branch ? ['--branch', branch] : [];
7
+ await git.clone(repoUrl, targetDir, options);
8
+ }
9
+ export async function fetchRepo(repoDir) {
10
+ const git = simpleGit(repoDir);
11
+ await git.fetch(['--all']);
12
+ }
13
+ export async function pullRepo(repoDir) {
14
+ const git = simpleGit(repoDir);
15
+ await git.pull();
16
+ }
17
+ export async function getCurrentCommit(repoDir) {
18
+ const git = simpleGit(repoDir);
19
+ const log = await git.log({ maxCount: 1 });
20
+ return log.latest?.hash ?? '';
21
+ }
22
+ export async function checkoutCommit(repoDir, commitSha) {
23
+ const git = simpleGit(repoDir);
24
+ await git.checkout(commitSha);
25
+ }
26
+ export async function isRepo(dir) {
27
+ if (!fs.existsSync(dir))
28
+ return false;
29
+ try {
30
+ const git = simpleGit(dir);
31
+ return await git.checkIsRepo();
32
+ }
33
+ catch {
34
+ return false;
35
+ }
36
+ }
37
+ export async function getRemoteUrl(repoDir) {
38
+ try {
39
+ const git = simpleGit(repoDir);
40
+ const remotes = await git.getRemotes(true);
41
+ const origin = remotes.find(r => r.name === 'origin');
42
+ return origin?.refs?.fetch ?? null;
43
+ }
44
+ catch {
45
+ return null;
46
+ }
47
+ }
48
+ export async function isBehindRemote(repoDir) {
49
+ try {
50
+ const git = simpleGit(repoDir);
51
+ await git.fetch();
52
+ const status = await git.status();
53
+ return { behind: status.behind > 0, commits: status.behind };
54
+ }
55
+ catch {
56
+ return { behind: false, commits: 0 };
57
+ }
58
+ }
59
+ export function ensureGitignore(hqRoot, entry) {
60
+ const gitignorePath = path.join(hqRoot, '.gitignore');
61
+ let content = '';
62
+ if (fs.existsSync(gitignorePath)) {
63
+ content = fs.readFileSync(gitignorePath, 'utf-8');
64
+ }
65
+ if (!content.includes(entry)) {
66
+ content = content.trimEnd() + '\n' + entry + '\n';
67
+ fs.writeFileSync(gitignorePath, content);
68
+ }
69
+ }
70
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAkB,MAAM,YAAY,CAAC;AAEvD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAe,EAAE,SAAiB,EAAE,MAAe;IACjF,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACnD,MAAM,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAe;IAC7C,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAe;IAC5C,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAe;IACpD,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;IAC3C,OAAO,GAAG,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAe,EAAE,SAAiB;IACrE,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,GAAW;IACtC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QAC3B,OAAO,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAe;IAChD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QACtD,OAAO,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAe;IAClD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAC/B,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC;QAClC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IACvC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAc,EAAE,KAAa;IAC3D,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACtD,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QACjC,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC;QAClD,EAAE,CAAC,aAAa,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC"}