@devclocked/cli 1.0.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 +78 -0
- package/dist/branding/banner.d.ts +16 -0
- package/dist/branding/banner.d.ts.map +1 -0
- package/dist/branding/banner.js +109 -0
- package/dist/branding/banner.js.map +1 -0
- package/dist/commands/flush.d.ts +6 -0
- package/dist/commands/flush.d.ts.map +1 -0
- package/dist/commands/flush.js +54 -0
- package/dist/commands/flush.js.map +1 -0
- package/dist/commands/login.d.ts +6 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +106 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +6 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +38 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/session.d.ts +6 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +90 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/status.d.ts +6 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +78 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +22 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/storage/FileStorageAdapter.d.ts +19 -0
- package/dist/storage/FileStorageAdapter.d.ts.map +1 -0
- package/dist/storage/FileStorageAdapter.js +80 -0
- package/dist/storage/FileStorageAdapter.js.map +1 -0
- package/dist/terminal/WrappedShell.d.ts +24 -0
- package/dist/terminal/WrappedShell.d.ts.map +1 -0
- package/dist/terminal/WrappedShell.js +121 -0
- package/dist/terminal/WrappedShell.js.map +1 -0
- package/dist/terminal/activityDetector.d.ts +33 -0
- package/dist/terminal/activityDetector.d.ts.map +1 -0
- package/dist/terminal/activityDetector.js +158 -0
- package/dist/terminal/activityDetector.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Status command - Show current tracking state
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.statusCommand = void 0;
|
|
10
|
+
const commander_1 = require("commander");
|
|
11
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
12
|
+
const tracker_core_1 = require("@devclocked/tracker-core");
|
|
13
|
+
const FileStorageAdapter_1 = require("../storage/FileStorageAdapter");
|
|
14
|
+
const config_1 = require("../config");
|
|
15
|
+
const banner_1 = require("../branding/banner");
|
|
16
|
+
async function showStatus() {
|
|
17
|
+
const storage = new FileStorageAdapter_1.FileStorageAdapter();
|
|
18
|
+
const client = new tracker_core_1.TrackerClient({
|
|
19
|
+
supabaseUrl: config_1.SUPABASE_URL,
|
|
20
|
+
supabaseAnonKey: config_1.SUPABASE_ANON_KEY,
|
|
21
|
+
source: 'cli',
|
|
22
|
+
clientId: `cli-${Date.now()}`,
|
|
23
|
+
debug: false,
|
|
24
|
+
}, storage);
|
|
25
|
+
// Stop auto-processing for CLI commands
|
|
26
|
+
client.stopAutoProcessing();
|
|
27
|
+
(0, banner_1.printHeader)('Status');
|
|
28
|
+
// Auth status
|
|
29
|
+
const isAuth = await client.isAuthenticated();
|
|
30
|
+
if (isAuth) {
|
|
31
|
+
const authState = await client.getAuthState();
|
|
32
|
+
(0, banner_1.printStatus)('Authenticated', authState?.email || 'unknown', true);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
(0, banner_1.printStatus)('Authenticated', 'No', false);
|
|
36
|
+
(0, banner_1.printInfo)('Run: devclocked login');
|
|
37
|
+
client.destroy();
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|
|
40
|
+
// Session status
|
|
41
|
+
try {
|
|
42
|
+
const session = await client.getActiveSessionFromBackend();
|
|
43
|
+
if (session && session.is_active) {
|
|
44
|
+
(0, banner_1.printStatus)('Active session', 'Yes', true);
|
|
45
|
+
(0, banner_1.printInfo)(` Source: ${chalk_1.default.cyan(session.source)}`);
|
|
46
|
+
(0, banner_1.printInfo)(` Started: ${chalk_1.default.gray((0, banner_1.formatTimeAgo)(session.started_at))}`);
|
|
47
|
+
if (session.last_tick_at) {
|
|
48
|
+
(0, banner_1.printInfo)(` Last tick: ${chalk_1.default.gray((0, banner_1.formatTimeAgo)(session.last_tick_at))}`);
|
|
49
|
+
}
|
|
50
|
+
(0, banner_1.printInfo)(` Tick count: ${chalk_1.default.cyan(String(session.tick_count || 0))}`);
|
|
51
|
+
if (session.repo_url) {
|
|
52
|
+
(0, banner_1.printInfo)(` Repository: ${chalk_1.default.cyan(session.repo_url)}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
(0, banner_1.printStatus)('Active session', 'No', false);
|
|
57
|
+
(0, banner_1.printInfo)('Start a session with: devclocked session');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
(0, banner_1.printStatus)('Active session', 'Unknown', false);
|
|
62
|
+
}
|
|
63
|
+
// Queue status
|
|
64
|
+
try {
|
|
65
|
+
const queueStats = await client.getQueueStats();
|
|
66
|
+
(0, banner_1.printInfo)(` Queue: ${chalk_1.default.cyan(String(queueStats.totalItems))} pending`);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// Ignore queue errors
|
|
70
|
+
}
|
|
71
|
+
console.log();
|
|
72
|
+
client.destroy();
|
|
73
|
+
process.exit(0);
|
|
74
|
+
}
|
|
75
|
+
exports.statusCommand = new commander_1.Command('status')
|
|
76
|
+
.description('Show current tracking status')
|
|
77
|
+
.action(showStatus);
|
|
78
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;AAEH,yCAAoC;AACpC,kDAA0B;AAC1B,2DAAyD;AACzD,sEAAmE;AACnE,sCAA4D;AAC5D,+CAK4B;AAE5B,KAAK,UAAU,UAAU;IACvB,MAAM,OAAO,GAAG,IAAI,uCAAkB,EAAE,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,4BAAa,CAAC;QAC/B,WAAW,EAAE,qBAAY;QACzB,eAAe,EAAE,0BAAiB;QAClC,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,OAAO,IAAI,CAAC,GAAG,EAAE,EAAE;QAC7B,KAAK,EAAE,KAAK;KACb,EAAE,OAAO,CAAC,CAAC;IAEZ,wCAAwC;IACxC,MAAM,CAAC,kBAAkB,EAAE,CAAC;IAE5B,IAAA,oBAAW,EAAC,QAAQ,CAAC,CAAC;IAEtB,cAAc;IACd,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,eAAe,EAAE,CAAC;IAC9C,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,YAAY,EAAE,CAAC;QAC9C,IAAA,oBAAW,EAAC,eAAe,EAAE,SAAS,EAAE,KAAK,IAAI,SAAS,EAAE,IAAI,CAAC,CAAC;IACpE,CAAC;SAAM,CAAC;QACN,IAAA,oBAAW,EAAC,eAAe,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QAC1C,IAAA,kBAAS,EAAC,uBAAuB,CAAC,CAAC;QACnC,MAAM,CAAC,OAAO,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,iBAAiB;IACjB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,2BAA2B,EAAE,CAAC;QAC3D,IAAI,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YACjC,IAAA,oBAAW,EAAC,gBAAgB,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;YAC3C,IAAA,kBAAS,EAAC,aAAa,eAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACrD,IAAA,kBAAS,EAAC,cAAc,eAAK,CAAC,IAAI,CAAC,IAAA,sBAAa,EAAC,OAAO,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC;YACzE,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;gBACzB,IAAA,kBAAS,EAAC,gBAAgB,eAAK,CAAC,IAAI,CAAC,IAAA,sBAAa,EAAC,OAAO,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC;YAC/E,CAAC;YACD,IAAA,kBAAS,EAAC,iBAAiB,eAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC1E,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACrB,IAAA,kBAAS,EAAC,iBAAiB,eAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAA,oBAAW,EAAC,gBAAgB,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;YAC3C,IAAA,kBAAS,EAAC,0CAA0C,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,IAAA,oBAAW,EAAC,gBAAgB,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC;IAED,eAAe;IACf,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC;QAChD,IAAA,kBAAS,EAAC,YAAY,eAAK,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,CAAC;IAC7E,CAAC;IAAC,MAAM,CAAC;QACP,sBAAsB;IACxB,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,MAAM,CAAC,OAAO,EAAE,CAAC;IACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAEY,QAAA,aAAa,GAAG,IAAI,mBAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,8BAA8B,CAAC;KAC3C,MAAM,CAAC,UAAU,CAAC,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Configuration Constants
|
|
3
|
+
*/
|
|
4
|
+
export declare const SUPABASE_URL = "https://haqfgkkmeglyrulmpist.supabase.co";
|
|
5
|
+
export declare const SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImhhcWZna2ttZWdseXJ1bG1waXN0Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTIwMDYyODcsImV4cCI6MjA2NzU4MjI4N30.fTonLdDRqqtV44tBcl0Z7ryvaSD5Gczy-OTkzHUw0o4";
|
|
6
|
+
export declare const CONFIG_DIR: string;
|
|
7
|
+
export declare const CONFIG_FILE: string;
|
|
8
|
+
export declare const REUSE_ACTIVE_WITHIN_MS = 120000;
|
|
9
|
+
export declare const END_SESSION_DEBOUNCE_MS = 60000;
|
|
10
|
+
export declare const IDLE_TIMEOUT_MS: number;
|
|
11
|
+
export declare const TICK_INTERVAL_MS = 30000;
|
|
12
|
+
export declare const CLI_VERSION = "1.0.0";
|
|
13
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,eAAO,MAAM,YAAY,6CAA6C,CAAC;AACvE,eAAO,MAAM,iBAAiB,qNAAqN,CAAC;AAGpP,eAAO,MAAM,UAAU,QAA2C,CAAC;AACnE,eAAO,MAAM,WAAW,QAA+B,CAAC;AAGxD,eAAO,MAAM,sBAAsB,SAAU,CAAC;AAC9C,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAC9C,eAAO,MAAM,eAAe,QAAiB,CAAC;AAC9C,eAAO,MAAM,gBAAgB,QAAS,CAAC;AAGvC,eAAO,MAAM,WAAW,UAAU,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CLI Configuration Constants
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CLI_VERSION = exports.TICK_INTERVAL_MS = exports.IDLE_TIMEOUT_MS = exports.END_SESSION_DEBOUNCE_MS = exports.REUSE_ACTIVE_WITHIN_MS = exports.CONFIG_FILE = exports.CONFIG_DIR = exports.SUPABASE_ANON_KEY = exports.SUPABASE_URL = void 0;
|
|
7
|
+
const os_1 = require("os");
|
|
8
|
+
const path_1 = require("path");
|
|
9
|
+
// Supabase configuration (same as other trackers)
|
|
10
|
+
exports.SUPABASE_URL = 'https://haqfgkkmeglyrulmpist.supabase.co';
|
|
11
|
+
exports.SUPABASE_ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImhhcWZna2ttZWdseXJ1bG1waXN0Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTIwMDYyODcsImV4cCI6MjA2NzU4MjI4N30.fTonLdDRqqtV44tBcl0Z7ryvaSD5Gczy-OTkzHUw0o4';
|
|
12
|
+
// Storage paths
|
|
13
|
+
exports.CONFIG_DIR = (0, path_1.join)((0, os_1.homedir)(), '.config', 'devclocked');
|
|
14
|
+
exports.CONFIG_FILE = (0, path_1.join)(exports.CONFIG_DIR, 'cli.json');
|
|
15
|
+
// Session constants (aligned with tracker-core)
|
|
16
|
+
exports.REUSE_ACTIVE_WITHIN_MS = 120000; // 2 minutes
|
|
17
|
+
exports.END_SESSION_DEBOUNCE_MS = 60000; // 1 minute
|
|
18
|
+
exports.IDLE_TIMEOUT_MS = 15 * 60 * 1000; // 15 minutes
|
|
19
|
+
exports.TICK_INTERVAL_MS = 30000; // 30 seconds minimum between ticks
|
|
20
|
+
// CLI version
|
|
21
|
+
exports.CLI_VERSION = '1.0.0';
|
|
22
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,2BAA6B;AAC7B,+BAA4B;AAE5B,kDAAkD;AACrC,QAAA,YAAY,GAAG,0CAA0C,CAAC;AAC1D,QAAA,iBAAiB,GAAG,kNAAkN,CAAC;AAEpP,gBAAgB;AACH,QAAA,UAAU,GAAG,IAAA,WAAI,EAAC,IAAA,YAAO,GAAE,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;AACtD,QAAA,WAAW,GAAG,IAAA,WAAI,EAAC,kBAAU,EAAE,UAAU,CAAC,CAAC;AAExD,gDAAgD;AACnC,QAAA,sBAAsB,GAAG,MAAO,CAAC,CAAC,YAAY;AAC9C,QAAA,uBAAuB,GAAG,KAAM,CAAC,CAAC,WAAW;AAC7C,QAAA,eAAe,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;AAC/C,QAAA,gBAAgB,GAAG,KAAM,CAAC,CAAC,mCAAmC;AAE3E,cAAc;AACD,QAAA,WAAW,GAAG,OAAO,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* DevClocked CLI - Terminal time tracking for developers
|
|
4
|
+
*
|
|
5
|
+
* Privacy guarantees:
|
|
6
|
+
* - Commands are NOT logged
|
|
7
|
+
* - Arguments are NOT logged
|
|
8
|
+
* - Output is NOT stored
|
|
9
|
+
* - Environment variables are NOT captured
|
|
10
|
+
* - Only tracked: timestamps, cwd, repo context
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* DevClocked CLI - Terminal time tracking for developers
|
|
5
|
+
*
|
|
6
|
+
* Privacy guarantees:
|
|
7
|
+
* - Commands are NOT logged
|
|
8
|
+
* - Arguments are NOT logged
|
|
9
|
+
* - Output is NOT stored
|
|
10
|
+
* - Environment variables are NOT captured
|
|
11
|
+
* - Only tracked: timestamps, cwd, repo context
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
const commander_1 = require("commander");
|
|
15
|
+
const login_1 = require("./commands/login");
|
|
16
|
+
const logout_1 = require("./commands/logout");
|
|
17
|
+
const session_1 = require("./commands/session");
|
|
18
|
+
const status_1 = require("./commands/status");
|
|
19
|
+
const flush_1 = require("./commands/flush");
|
|
20
|
+
const program = new commander_1.Command();
|
|
21
|
+
program
|
|
22
|
+
.name('devclocked')
|
|
23
|
+
.description('DevClocked CLI - Terminal time tracking for developers')
|
|
24
|
+
.version('1.0.0');
|
|
25
|
+
program.addCommand(login_1.loginCommand);
|
|
26
|
+
program.addCommand(logout_1.logoutCommand);
|
|
27
|
+
program.addCommand(session_1.sessionCommand);
|
|
28
|
+
program.addCommand(status_1.statusCommand);
|
|
29
|
+
program.addCommand(flush_1.flushCommand);
|
|
30
|
+
program.parse();
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AACA;;;;;;;;;GASG;;AAEH,yCAAoC;AACpC,4CAAgD;AAChD,8CAAkD;AAClD,gDAAoD;AACpD,8CAAkD;AAClD,4CAAgD;AAEhD,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,wDAAwD,CAAC;KACrE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,UAAU,CAAC,oBAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,wBAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,oBAAY,CAAC,CAAC;AAEjC,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File-based storage adapter for CLI
|
|
3
|
+
* Stores data in ~/.config/devclocked/cli.json
|
|
4
|
+
*/
|
|
5
|
+
import { StorageAdapter } from '@devclocked/tracker-core';
|
|
6
|
+
export declare class FileStorageAdapter extends StorageAdapter {
|
|
7
|
+
private data;
|
|
8
|
+
private loaded;
|
|
9
|
+
constructor();
|
|
10
|
+
private ensureConfigDir;
|
|
11
|
+
private loadFromDisk;
|
|
12
|
+
private saveToDisk;
|
|
13
|
+
get(key: string): Promise<string | null>;
|
|
14
|
+
set(key: string, value: string): Promise<void>;
|
|
15
|
+
remove(key: string): Promise<void>;
|
|
16
|
+
clear(): Promise<void>;
|
|
17
|
+
keys(): Promise<string[]>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=FileStorageAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileStorageAdapter.d.ts","sourceRoot":"","sources":["../../src/storage/FileStorageAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAS1D,qBAAa,kBAAmB,SAAQ,cAAc;IACpD,OAAO,CAAC,IAAI,CAAmB;IAC/B,OAAO,CAAC,MAAM,CAAS;;IAQvB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,UAAU;IAkBZ,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAKxC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM9C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtB,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CAIhC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* File-based storage adapter for CLI
|
|
4
|
+
* Stores data in ~/.config/devclocked/cli.json
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.FileStorageAdapter = void 0;
|
|
8
|
+
const tracker_core_1 = require("@devclocked/tracker-core");
|
|
9
|
+
const fs_1 = require("fs");
|
|
10
|
+
const path_1 = require("path");
|
|
11
|
+
const config_1 = require("../config");
|
|
12
|
+
class FileStorageAdapter extends tracker_core_1.StorageAdapter {
|
|
13
|
+
constructor() {
|
|
14
|
+
super();
|
|
15
|
+
this.data = {};
|
|
16
|
+
this.loaded = false;
|
|
17
|
+
this.ensureConfigDir();
|
|
18
|
+
this.loadFromDisk();
|
|
19
|
+
}
|
|
20
|
+
ensureConfigDir() {
|
|
21
|
+
if (!(0, fs_1.existsSync)(config_1.CONFIG_DIR)) {
|
|
22
|
+
(0, fs_1.mkdirSync)(config_1.CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
loadFromDisk() {
|
|
26
|
+
if (this.loaded)
|
|
27
|
+
return;
|
|
28
|
+
try {
|
|
29
|
+
if ((0, fs_1.existsSync)(config_1.CONFIG_FILE)) {
|
|
30
|
+
const content = (0, fs_1.readFileSync)(config_1.CONFIG_FILE, 'utf-8');
|
|
31
|
+
this.data = JSON.parse(content);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
// Start fresh if file is corrupted
|
|
36
|
+
this.data = {};
|
|
37
|
+
}
|
|
38
|
+
this.loaded = true;
|
|
39
|
+
}
|
|
40
|
+
saveToDisk() {
|
|
41
|
+
try {
|
|
42
|
+
const dir = (0, path_1.dirname)(config_1.CONFIG_FILE);
|
|
43
|
+
if (!(0, fs_1.existsSync)(dir)) {
|
|
44
|
+
(0, fs_1.mkdirSync)(dir, { recursive: true, mode: 0o700 });
|
|
45
|
+
}
|
|
46
|
+
(0, fs_1.writeFileSync)(config_1.CONFIG_FILE, JSON.stringify(this.data, null, 2), {
|
|
47
|
+
mode: 0o600, // User-only read/write
|
|
48
|
+
});
|
|
49
|
+
// Ensure permissions are correct
|
|
50
|
+
(0, fs_1.chmodSync)(config_1.CONFIG_FILE, 0o600);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
console.error('Failed to save config:', error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async get(key) {
|
|
57
|
+
this.loadFromDisk();
|
|
58
|
+
return this.data[key] ?? null;
|
|
59
|
+
}
|
|
60
|
+
async set(key, value) {
|
|
61
|
+
this.loadFromDisk();
|
|
62
|
+
this.data[key] = value;
|
|
63
|
+
this.saveToDisk();
|
|
64
|
+
}
|
|
65
|
+
async remove(key) {
|
|
66
|
+
this.loadFromDisk();
|
|
67
|
+
delete this.data[key];
|
|
68
|
+
this.saveToDisk();
|
|
69
|
+
}
|
|
70
|
+
async clear() {
|
|
71
|
+
this.data = {};
|
|
72
|
+
this.saveToDisk();
|
|
73
|
+
}
|
|
74
|
+
async keys() {
|
|
75
|
+
this.loadFromDisk();
|
|
76
|
+
return Object.keys(this.data);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.FileStorageAdapter = FileStorageAdapter;
|
|
80
|
+
//# sourceMappingURL=FileStorageAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileStorageAdapter.js","sourceRoot":"","sources":["../../src/storage/FileStorageAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wrapped Shell - PTY wrapper for terminal activity detection
|
|
3
|
+
*
|
|
4
|
+
* Privacy guarantees:
|
|
5
|
+
* - Commands are NOT logged
|
|
6
|
+
* - Output is NOT stored
|
|
7
|
+
* - Only timestamps and cwd are tracked
|
|
8
|
+
*/
|
|
9
|
+
export type ActivityCallback = (cwd: string) => void;
|
|
10
|
+
export type ExitCallback = (code: number) => void;
|
|
11
|
+
export declare class WrappedShell {
|
|
12
|
+
private ptyProcess;
|
|
13
|
+
private cwd;
|
|
14
|
+
private shell;
|
|
15
|
+
private activityCallback;
|
|
16
|
+
private exitCallback;
|
|
17
|
+
constructor(cwd: string, activityCallback: ActivityCallback, exitCallback: ExitCallback);
|
|
18
|
+
private detectShell;
|
|
19
|
+
getShell(): string;
|
|
20
|
+
spawn(): void;
|
|
21
|
+
private cleanup;
|
|
22
|
+
destroy(): void;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=WrappedShell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WrappedShell.d.ts","sourceRoot":"","sources":["../../src/terminal/WrappedShell.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;AACrD,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;AAElD,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAyB;IAC3C,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,YAAY,CAAe;gBAGjC,GAAG,EAAE,MAAM,EACX,gBAAgB,EAAE,gBAAgB,EAClC,YAAY,EAAE,YAAY;IAQ5B,OAAO,CAAC,WAAW;IAWnB,QAAQ,IAAI,MAAM;IAIlB,KAAK,IAAI,IAAI;IAiDb,OAAO,CAAC,OAAO;IAOf,OAAO,IAAI,IAAI;CAOhB"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Wrapped Shell - PTY wrapper for terminal activity detection
|
|
4
|
+
*
|
|
5
|
+
* Privacy guarantees:
|
|
6
|
+
* - Commands are NOT logged
|
|
7
|
+
* - Output is NOT stored
|
|
8
|
+
* - Only timestamps and cwd are tracked
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.WrappedShell = void 0;
|
|
45
|
+
const pty = __importStar(require("node-pty"));
|
|
46
|
+
const os_1 = require("os");
|
|
47
|
+
class WrappedShell {
|
|
48
|
+
constructor(cwd, activityCallback, exitCallback) {
|
|
49
|
+
this.ptyProcess = null;
|
|
50
|
+
this.cwd = cwd;
|
|
51
|
+
this.activityCallback = activityCallback;
|
|
52
|
+
this.exitCallback = exitCallback;
|
|
53
|
+
this.shell = this.detectShell();
|
|
54
|
+
}
|
|
55
|
+
detectShell() {
|
|
56
|
+
const shellEnv = process.env.SHELL;
|
|
57
|
+
if (shellEnv)
|
|
58
|
+
return shellEnv;
|
|
59
|
+
if ((0, os_1.platform)() === 'win32') {
|
|
60
|
+
return process.env.COMSPEC || 'cmd.exe';
|
|
61
|
+
}
|
|
62
|
+
return '/bin/sh';
|
|
63
|
+
}
|
|
64
|
+
getShell() {
|
|
65
|
+
return this.shell;
|
|
66
|
+
}
|
|
67
|
+
spawn() {
|
|
68
|
+
const isWindows = (0, os_1.platform)() === 'win32';
|
|
69
|
+
this.ptyProcess = pty.spawn(this.shell, [], {
|
|
70
|
+
name: 'xterm-256color',
|
|
71
|
+
cols: process.stdout.columns || 80,
|
|
72
|
+
rows: process.stdout.rows || 24,
|
|
73
|
+
cwd: this.cwd,
|
|
74
|
+
env: process.env,
|
|
75
|
+
useConpty: isWindows,
|
|
76
|
+
});
|
|
77
|
+
// Pipe PTY output to stdout (transparent)
|
|
78
|
+
this.ptyProcess.onData((data) => {
|
|
79
|
+
process.stdout.write(data);
|
|
80
|
+
});
|
|
81
|
+
// Pipe stdin to PTY
|
|
82
|
+
if (process.stdin.isTTY) {
|
|
83
|
+
process.stdin.setRawMode(true);
|
|
84
|
+
}
|
|
85
|
+
process.stdin.resume();
|
|
86
|
+
process.stdin.setEncoding('utf8');
|
|
87
|
+
process.stdin.on('data', (data) => {
|
|
88
|
+
if (this.ptyProcess) {
|
|
89
|
+
this.ptyProcess.write(data.toString());
|
|
90
|
+
// Signal activity on input (NOT logging the content)
|
|
91
|
+
this.activityCallback(this.cwd);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
// Handle terminal resize
|
|
95
|
+
process.stdout.on('resize', () => {
|
|
96
|
+
if (this.ptyProcess) {
|
|
97
|
+
this.ptyProcess.resize(process.stdout.columns || 80, process.stdout.rows || 24);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
// Handle shell exit
|
|
101
|
+
this.ptyProcess.onExit(({ exitCode }) => {
|
|
102
|
+
this.cleanup();
|
|
103
|
+
this.exitCallback(exitCode);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
cleanup() {
|
|
107
|
+
if (process.stdin.isTTY) {
|
|
108
|
+
process.stdin.setRawMode(false);
|
|
109
|
+
}
|
|
110
|
+
process.stdin.pause();
|
|
111
|
+
}
|
|
112
|
+
destroy() {
|
|
113
|
+
this.cleanup();
|
|
114
|
+
if (this.ptyProcess) {
|
|
115
|
+
this.ptyProcess.kill();
|
|
116
|
+
this.ptyProcess = null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
exports.WrappedShell = WrappedShell;
|
|
121
|
+
//# sourceMappingURL=WrappedShell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WrappedShell.js","sourceRoot":"","sources":["../../src/terminal/WrappedShell.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Activity Detector - Debounces activity and detects git repo context
|
|
3
|
+
*
|
|
4
|
+
* Privacy guarantees:
|
|
5
|
+
* - Only tracks timestamps and cwd
|
|
6
|
+
* - No command or output logging
|
|
7
|
+
*/
|
|
8
|
+
import { TrackerClient } from '@devclocked/tracker-core';
|
|
9
|
+
export interface RepoContext {
|
|
10
|
+
repoUrl?: string;
|
|
11
|
+
repoFullName?: string;
|
|
12
|
+
branch?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class ActivityDetector {
|
|
15
|
+
private lastTickAt;
|
|
16
|
+
private lastActivityAt;
|
|
17
|
+
private idleTimer;
|
|
18
|
+
private client;
|
|
19
|
+
private shell;
|
|
20
|
+
private onIdle;
|
|
21
|
+
private cachedRepo;
|
|
22
|
+
constructor(client: TrackerClient, shell: string, onIdle: () => void);
|
|
23
|
+
onActivity(cwd: string): void;
|
|
24
|
+
private resetIdleTimer;
|
|
25
|
+
private emitTick;
|
|
26
|
+
private detectGitRepo;
|
|
27
|
+
private findGitDir;
|
|
28
|
+
private normalizeRepoUrl;
|
|
29
|
+
private extractRepoFullName;
|
|
30
|
+
getLastActivityAt(): number;
|
|
31
|
+
destroy(): void;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=activityDetector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activityDetector.d.ts","sourceRoot":"","sources":["../../src/terminal/activityDetector.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAMzD,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,UAAU,CAAsD;gBAGtE,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,IAAI;IAOpB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAgB7B,OAAO,CAAC,cAAc;YAUR,QAAQ;IActB,OAAO,CAAC,aAAa;IAsDrB,OAAO,CAAC,UAAU;IAclB,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,mBAAmB;IA2B3B,iBAAiB,IAAI,MAAM;IAI3B,OAAO,IAAI,IAAI;CAMhB"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Activity Detector - Debounces activity and detects git repo context
|
|
4
|
+
*
|
|
5
|
+
* Privacy guarantees:
|
|
6
|
+
* - Only tracks timestamps and cwd
|
|
7
|
+
* - No command or output logging
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.ActivityDetector = void 0;
|
|
11
|
+
const child_process_1 = require("child_process");
|
|
12
|
+
const fs_1 = require("fs");
|
|
13
|
+
const path_1 = require("path");
|
|
14
|
+
const config_1 = require("../config");
|
|
15
|
+
class ActivityDetector {
|
|
16
|
+
constructor(client, shell, onIdle) {
|
|
17
|
+
this.lastTickAt = 0;
|
|
18
|
+
this.lastActivityAt = 0;
|
|
19
|
+
this.idleTimer = null;
|
|
20
|
+
this.cachedRepo = null;
|
|
21
|
+
this.client = client;
|
|
22
|
+
this.shell = shell;
|
|
23
|
+
this.onIdle = onIdle;
|
|
24
|
+
}
|
|
25
|
+
onActivity(cwd) {
|
|
26
|
+
const now = Date.now();
|
|
27
|
+
this.lastActivityAt = now;
|
|
28
|
+
// Reset idle timer
|
|
29
|
+
this.resetIdleTimer();
|
|
30
|
+
// Debounce ticks
|
|
31
|
+
if (now - this.lastTickAt < config_1.TICK_INTERVAL_MS) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
this.lastTickAt = now;
|
|
35
|
+
this.emitTick(cwd);
|
|
36
|
+
}
|
|
37
|
+
resetIdleTimer() {
|
|
38
|
+
if (this.idleTimer) {
|
|
39
|
+
clearTimeout(this.idleTimer);
|
|
40
|
+
}
|
|
41
|
+
this.idleTimer = setTimeout(() => {
|
|
42
|
+
this.onIdle();
|
|
43
|
+
}, config_1.IDLE_TIMEOUT_MS);
|
|
44
|
+
}
|
|
45
|
+
async emitTick(cwd) {
|
|
46
|
+
const repoContext = this.detectGitRepo(cwd);
|
|
47
|
+
try {
|
|
48
|
+
await this.client.sendTick('terminal', 'window', {
|
|
49
|
+
repo_url: repoContext.repoUrl,
|
|
50
|
+
branch: repoContext.branch,
|
|
51
|
+
repository_full_name: repoContext.repoFullName,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
// Queue will retry
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
detectGitRepo(cwd) {
|
|
59
|
+
// Use cache if same cwd
|
|
60
|
+
if (this.cachedRepo && this.cachedRepo.cwd === cwd) {
|
|
61
|
+
return this.cachedRepo.context;
|
|
62
|
+
}
|
|
63
|
+
const context = {};
|
|
64
|
+
try {
|
|
65
|
+
// Find git root
|
|
66
|
+
const gitDir = this.findGitDir(cwd);
|
|
67
|
+
if (!gitDir) {
|
|
68
|
+
this.cachedRepo = { cwd, context };
|
|
69
|
+
return context;
|
|
70
|
+
}
|
|
71
|
+
// Get remote URL
|
|
72
|
+
try {
|
|
73
|
+
const remoteUrl = (0, child_process_1.execSync)('git config --get remote.origin.url', {
|
|
74
|
+
cwd,
|
|
75
|
+
encoding: 'utf-8',
|
|
76
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
77
|
+
}).trim();
|
|
78
|
+
if (remoteUrl) {
|
|
79
|
+
context.repoUrl = this.normalizeRepoUrl(remoteUrl);
|
|
80
|
+
context.repoFullName = this.extractRepoFullName(remoteUrl);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// No remote
|
|
85
|
+
}
|
|
86
|
+
// Get current branch
|
|
87
|
+
try {
|
|
88
|
+
const branch = (0, child_process_1.execSync)('git rev-parse --abbrev-ref HEAD', {
|
|
89
|
+
cwd,
|
|
90
|
+
encoding: 'utf-8',
|
|
91
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
92
|
+
}).trim();
|
|
93
|
+
if (branch && branch !== 'HEAD') {
|
|
94
|
+
context.branch = branch;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// Not in git repo or detached HEAD
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// Git not available
|
|
103
|
+
}
|
|
104
|
+
this.cachedRepo = { cwd, context };
|
|
105
|
+
return context;
|
|
106
|
+
}
|
|
107
|
+
findGitDir(startPath) {
|
|
108
|
+
let current = startPath;
|
|
109
|
+
while (current !== (0, path_1.dirname)(current)) {
|
|
110
|
+
const gitPath = (0, path_1.join)(current, '.git');
|
|
111
|
+
if ((0, fs_1.existsSync)(gitPath)) {
|
|
112
|
+
return gitPath;
|
|
113
|
+
}
|
|
114
|
+
current = (0, path_1.dirname)(current);
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
normalizeRepoUrl(url) {
|
|
119
|
+
// git@github.com:owner/repo.git -> https://github.com/owner/repo
|
|
120
|
+
let normalized = url
|
|
121
|
+
.replace(/^git@([^:]+):(.+)\.git$/, 'https://$1/$2')
|
|
122
|
+
.replace(/\.git$/, '');
|
|
123
|
+
return normalized;
|
|
124
|
+
}
|
|
125
|
+
extractRepoFullName(url) {
|
|
126
|
+
// Extract owner/repo from various URL formats
|
|
127
|
+
let path = '';
|
|
128
|
+
// SSH format: git@github.com:owner/repo.git
|
|
129
|
+
const sshMatch = /^git@[^:]+:(.+?)(?:\.git)?$/.exec(url);
|
|
130
|
+
if (sshMatch) {
|
|
131
|
+
path = sshMatch[1];
|
|
132
|
+
}
|
|
133
|
+
// HTTPS format: https://github.com/owner/repo.git
|
|
134
|
+
const httpsMatch = /^https?:\/\/[^/]+\/(.+?)(?:\.git)?$/.exec(url);
|
|
135
|
+
if (httpsMatch) {
|
|
136
|
+
path = httpsMatch[1];
|
|
137
|
+
}
|
|
138
|
+
if (!path)
|
|
139
|
+
return undefined;
|
|
140
|
+
// Return owner/repo format
|
|
141
|
+
const parts = path.split('/');
|
|
142
|
+
if (parts.length >= 2) {
|
|
143
|
+
return `${parts[0]}/${parts[1]}`.toLowerCase();
|
|
144
|
+
}
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
getLastActivityAt() {
|
|
148
|
+
return this.lastActivityAt;
|
|
149
|
+
}
|
|
150
|
+
destroy() {
|
|
151
|
+
if (this.idleTimer) {
|
|
152
|
+
clearTimeout(this.idleTimer);
|
|
153
|
+
this.idleTimer = null;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
exports.ActivityDetector = ActivityDetector;
|
|
158
|
+
//# sourceMappingURL=activityDetector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activityDetector.js","sourceRoot":"","sources":["../../src/terminal/activityDetector.ts"],"names":[],"mappings":"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"}
|