episoda 0.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.
Files changed (111) hide show
  1. package/dist/commands/auth.d.ts +22 -0
  2. package/dist/commands/auth.d.ts.map +1 -0
  3. package/dist/commands/auth.js +384 -0
  4. package/dist/commands/auth.js.map +1 -0
  5. package/dist/commands/dev.d.ts +20 -0
  6. package/dist/commands/dev.d.ts.map +1 -0
  7. package/dist/commands/dev.js +305 -0
  8. package/dist/commands/dev.js.map +1 -0
  9. package/dist/commands/status.d.ts +9 -0
  10. package/dist/commands/status.d.ts.map +1 -0
  11. package/dist/commands/status.js +75 -0
  12. package/dist/commands/status.js.map +1 -0
  13. package/dist/commands/stop.d.ts +17 -0
  14. package/dist/commands/stop.d.ts.map +1 -0
  15. package/dist/commands/stop.js +81 -0
  16. package/dist/commands/stop.js.map +1 -0
  17. package/dist/core/auth.d.ts +26 -0
  18. package/dist/core/auth.d.ts.map +1 -0
  19. package/dist/core/auth.js +113 -0
  20. package/dist/core/auth.js.map +1 -0
  21. package/dist/core/command-protocol.d.ts +262 -0
  22. package/dist/core/command-protocol.d.ts.map +1 -0
  23. package/dist/core/command-protocol.js +13 -0
  24. package/dist/core/command-protocol.js.map +1 -0
  25. package/dist/core/connection-manager.d.ts +58 -0
  26. package/dist/core/connection-manager.d.ts.map +1 -0
  27. package/dist/core/connection-manager.js +215 -0
  28. package/dist/core/connection-manager.js.map +1 -0
  29. package/dist/core/errors.d.ts +18 -0
  30. package/dist/core/errors.d.ts.map +1 -0
  31. package/dist/core/errors.js +55 -0
  32. package/dist/core/errors.js.map +1 -0
  33. package/dist/core/git-executor.d.ts +157 -0
  34. package/dist/core/git-executor.d.ts.map +1 -0
  35. package/dist/core/git-executor.js +1605 -0
  36. package/dist/core/git-executor.js.map +1 -0
  37. package/dist/core/git-parser.d.ts +40 -0
  38. package/dist/core/git-parser.d.ts.map +1 -0
  39. package/dist/core/git-parser.js +194 -0
  40. package/dist/core/git-parser.js.map +1 -0
  41. package/dist/core/git-validator.d.ts +42 -0
  42. package/dist/core/git-validator.d.ts.map +1 -0
  43. package/dist/core/git-validator.js +102 -0
  44. package/dist/core/git-validator.js.map +1 -0
  45. package/dist/core/index.d.ts +17 -0
  46. package/dist/core/index.d.ts.map +1 -0
  47. package/dist/core/index.js +41 -0
  48. package/dist/core/index.js.map +1 -0
  49. package/dist/core/version.d.ts +9 -0
  50. package/dist/core/version.d.ts.map +1 -0
  51. package/dist/core/version.js +19 -0
  52. package/dist/core/version.js.map +1 -0
  53. package/dist/core/websocket-client.d.ts +122 -0
  54. package/dist/core/websocket-client.d.ts.map +1 -0
  55. package/dist/core/websocket-client.js +438 -0
  56. package/dist/core/websocket-client.js.map +1 -0
  57. package/dist/daemon/daemon-manager.d.ts +71 -0
  58. package/dist/daemon/daemon-manager.d.ts.map +1 -0
  59. package/dist/daemon/daemon-manager.js +289 -0
  60. package/dist/daemon/daemon-manager.js.map +1 -0
  61. package/dist/daemon/daemon-process.d.ts +13 -0
  62. package/dist/daemon/daemon-process.d.ts.map +1 -0
  63. package/dist/daemon/daemon-process.js +608 -0
  64. package/dist/daemon/daemon-process.js.map +1 -0
  65. package/dist/daemon/machine-id.d.ts +36 -0
  66. package/dist/daemon/machine-id.d.ts.map +1 -0
  67. package/dist/daemon/machine-id.js +195 -0
  68. package/dist/daemon/machine-id.js.map +1 -0
  69. package/dist/daemon/project-tracker.d.ts +92 -0
  70. package/dist/daemon/project-tracker.d.ts.map +1 -0
  71. package/dist/daemon/project-tracker.js +259 -0
  72. package/dist/daemon/project-tracker.js.map +1 -0
  73. package/dist/dev-wrapper.d.ts +88 -0
  74. package/dist/dev-wrapper.d.ts.map +1 -0
  75. package/dist/dev-wrapper.js +288 -0
  76. package/dist/dev-wrapper.js.map +1 -0
  77. package/dist/framework-detector.d.ts +29 -0
  78. package/dist/framework-detector.d.ts.map +1 -0
  79. package/dist/framework-detector.js +276 -0
  80. package/dist/framework-detector.js.map +1 -0
  81. package/dist/git-helpers/git-credential-helper.d.ts +29 -0
  82. package/dist/git-helpers/git-credential-helper.d.ts.map +1 -0
  83. package/dist/git-helpers/git-credential-helper.js +349 -0
  84. package/dist/git-helpers/git-credential-helper.js.map +1 -0
  85. package/dist/hooks/post-checkout +296 -0
  86. package/dist/hooks/pre-commit +139 -0
  87. package/dist/index.d.ts +8 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +102 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/ipc/ipc-client.d.ts +95 -0
  92. package/dist/ipc/ipc-client.d.ts.map +1 -0
  93. package/dist/ipc/ipc-client.js +204 -0
  94. package/dist/ipc/ipc-client.js.map +1 -0
  95. package/dist/ipc/ipc-server.d.ts +55 -0
  96. package/dist/ipc/ipc-server.d.ts.map +1 -0
  97. package/dist/ipc/ipc-server.js +177 -0
  98. package/dist/ipc/ipc-server.js.map +1 -0
  99. package/dist/output.d.ts +48 -0
  100. package/dist/output.d.ts.map +1 -0
  101. package/dist/output.js +129 -0
  102. package/dist/output.js.map +1 -0
  103. package/dist/utils/port-check.d.ts +15 -0
  104. package/dist/utils/port-check.d.ts.map +1 -0
  105. package/dist/utils/port-check.js +79 -0
  106. package/dist/utils/port-check.js.map +1 -0
  107. package/dist/utils/update-checker.d.ts +23 -0
  108. package/dist/utils/update-checker.d.ts.map +1 -0
  109. package/dist/utils/update-checker.js +95 -0
  110. package/dist/utils/update-checker.js.map +1 -0
  111. package/package.json +51 -0
@@ -0,0 +1,139 @@
1
+ #!/bin/bash
2
+ #
3
+ # EP490: Prevent commits directly to main branch
4
+ # EP647: Extended to block ALL non-module branches (except hotfix/*)
5
+ # This hook enforces the module workflow for all development work
6
+ #
7
+
8
+ BRANCH=$(git branch --show-current)
9
+
10
+ # Allow module branches (module/EP123-description)
11
+ # EP647: But warn if it's a cloud module being committed locally
12
+ if [[ "$BRANCH" == module/* ]]; then
13
+ # Extract module UID from branch name (e.g., EP647 from module/EP647-description)
14
+ MODULE_UID=$(echo "$BRANCH" | grep -oE 'EP[0-9]+')
15
+
16
+ if [ -n "$MODULE_UID" ]; then
17
+ # Check if this is a cloud module
18
+ # Read config from ~/.episoda/config.json
19
+ CONFIG_FILE="$HOME/.episoda/config.json"
20
+
21
+ if [ -f "$CONFIG_FILE" ]; then
22
+ # Extract access_token and api_url using node (more reliable than jq which may not be installed)
23
+ CLOUD_CHECK=$(node -e "
24
+ const fs = require('fs');
25
+ const https = require('https');
26
+ const http = require('http');
27
+
28
+ try {
29
+ const config = JSON.parse(fs.readFileSync('$CONFIG_FILE', 'utf8'));
30
+ const token = config.access_token;
31
+ const apiUrl = config.api_url || 'https://episoda.dev';
32
+
33
+ if (!token) {
34
+ console.log('SKIP:No token');
35
+ process.exit(0);
36
+ }
37
+
38
+ const url = new URL('/api/modules/$MODULE_UID', apiUrl);
39
+ const client = url.protocol === 'https:' ? https : http;
40
+
41
+ const req = client.request(url, {
42
+ method: 'GET',
43
+ headers: {
44
+ 'Authorization': 'Bearer ' + token,
45
+ 'Content-Type': 'application/json'
46
+ },
47
+ timeout: 3000
48
+ }, (res) => {
49
+ let data = '';
50
+ res.on('data', chunk => data += chunk);
51
+ res.on('end', () => {
52
+ try {
53
+ const json = JSON.parse(data);
54
+ if (json.success && json.moduleRecord && json.moduleRecord.dev_mode === 'cloud') {
55
+ console.log('CLOUD:' + json.moduleRecord.title);
56
+ } else {
57
+ console.log('LOCAL');
58
+ }
59
+ } catch (e) {
60
+ console.log('SKIP:Parse error');
61
+ }
62
+ });
63
+ });
64
+
65
+ req.on('error', () => console.log('SKIP:Network error'));
66
+ req.on('timeout', () => { req.destroy(); console.log('SKIP:Timeout'); });
67
+ req.end();
68
+ } catch (e) {
69
+ console.log('SKIP:Config error');
70
+ }
71
+ " 2>/dev/null)
72
+
73
+ if [[ "$CLOUD_CHECK" == CLOUD:* ]]; then
74
+ MODULE_TITLE="${CLOUD_CHECK#CLOUD:}"
75
+ echo ""
76
+ echo "⚠️ Warning: '$MODULE_UID' is a CLOUD module"
77
+ echo ""
78
+ echo "Module: $MODULE_TITLE"
79
+ echo ""
80
+ echo "This module is configured for cloud development (dev_mode: cloud)."
81
+ echo "Local commits may cause sync issues with the cloud environment."
82
+ echo ""
83
+ echo "Recommended workflow:"
84
+ echo " 1. Connect to cloud VM: episoda dev ssh $MODULE_UID"
85
+ echo " 2. Make changes and commit in the cloud environment"
86
+ echo ""
87
+ echo "To bypass this warning:"
88
+ echo " git commit --no-verify"
89
+ echo ""
90
+ exit 1
91
+ fi
92
+ fi
93
+ fi
94
+
95
+ # Module branch is allowed (local module or cloud check skipped/failed)
96
+ exit 0
97
+ fi
98
+
99
+ # Allow hotfix branches (hotfix/description) for emergency fixes
100
+ if [[ "$BRANCH" == hotfix/* ]]; then
101
+ exit 0
102
+ fi
103
+
104
+ # Block main branch with specific message
105
+ if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "master" ]; then
106
+ echo ""
107
+ echo "❌ Cannot commit directly to main branch!"
108
+ echo ""
109
+ echo "Please create a module first:"
110
+ echo " 1. Go to https://episoda.dev/workflow"
111
+ echo " 2. Create a new module (or select existing)"
112
+ echo " 3. Move it to 'Doing' state to create a branch"
113
+ echo " 4. Then switch to the module branch:"
114
+ echo " git stash && git checkout module/EP-XXX-... && git stash pop"
115
+ echo ""
116
+ echo "To bypass this check (not recommended):"
117
+ echo " git commit --no-verify"
118
+ echo ""
119
+ exit 1
120
+ fi
121
+
122
+ # Block all other branches
123
+ echo ""
124
+ echo "❌ Cannot commit on branch '$BRANCH'"
125
+ echo ""
126
+ echo "All work must be done on module branches (module/EP-XXX-...)."
127
+ echo "This ensures proper tracking and code review workflow."
128
+ echo ""
129
+ echo "Options:"
130
+ echo " 1. Create a module at https://episoda.dev/workflow"
131
+ echo " Move it to 'Doing' to create a branch, then checkout"
132
+ echo ""
133
+ echo " 2. For emergency hotfixes, use a hotfix/* branch:"
134
+ echo " git checkout -b hotfix/description"
135
+ echo ""
136
+ echo "To bypass this check (not recommended):"
137
+ echo " git commit --no-verify"
138
+ echo ""
139
+ exit 1
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Episoda CLI
4
+ *
5
+ * Local development workflow orchestration for episoda.dev
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;GAIG"}
package/dist/index.js ADDED
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Episoda CLI
5
+ *
6
+ * Local development workflow orchestration for episoda.dev
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ const commander_1 = require("commander");
10
+ const core_1 = require("./core");
11
+ const dev_1 = require("./commands/dev");
12
+ const auth_1 = require("./commands/auth");
13
+ const status_1 = require("./commands/status");
14
+ const stop_1 = require("./commands/stop");
15
+ const output_1 = require("./output");
16
+ commander_1.program
17
+ .name('episoda')
18
+ .description('Episoda local development workflow orchestration')
19
+ .version(core_1.VERSION);
20
+ // Auth command (K722)
21
+ commander_1.program
22
+ .command('auth')
23
+ .description('Authenticate to Episoda via OAuth and configure CLI')
24
+ .option('--api-url <url>', 'API URL (default: https://episoda.dev)')
25
+ .action(async (options) => {
26
+ try {
27
+ await (0, auth_1.authCommand)(options);
28
+ }
29
+ catch (error) {
30
+ output_1.status.error(`Authentication failed: ${error instanceof Error ? error.message : String(error)}`);
31
+ process.exit(1);
32
+ }
33
+ });
34
+ // Dev command
35
+ commander_1.program
36
+ .command('dev')
37
+ .description('Start dev server with Episoda orchestration')
38
+ .option('--auto-restart', 'Auto-restart dev server if it crashes')
39
+ .option('--connection-only', 'Connection-only mode (don\'t start dev server)')
40
+ .allowUnknownOption()
41
+ .action(async (options, cmd) => {
42
+ try {
43
+ // Extract command after 'dev' as the dev server command
44
+ // e.g., 'episoda dev -- npm run dev' -> ["npm", "run", "dev"]
45
+ const args = process.argv.slice(process.argv.indexOf('dev') + 1);
46
+ // Remove '--' separator if present
47
+ const separatorIndex = args.indexOf('--');
48
+ const command = separatorIndex >= 0 ? args.slice(separatorIndex + 1) : [];
49
+ // Filter out our own options
50
+ const filteredCommand = command.filter(arg => arg !== '--auto-restart' && arg !== '--connection-only');
51
+ await (0, dev_1.devCommand)({
52
+ command: options.connectionOnly ? [] : (filteredCommand.length > 0 ? filteredCommand : undefined),
53
+ autoRestart: options.autoRestart
54
+ });
55
+ }
56
+ catch (error) {
57
+ output_1.status.error(`Dev command failed: ${error instanceof Error ? error.message : String(error)}`);
58
+ process.exit(1);
59
+ }
60
+ });
61
+ // Status command
62
+ commander_1.program
63
+ .command('status')
64
+ .description('Show connection status')
65
+ .action(async () => {
66
+ try {
67
+ await (0, status_1.statusCommand)();
68
+ }
69
+ catch (error) {
70
+ output_1.status.error(`Status check failed: ${error instanceof Error ? error.message : String(error)}`);
71
+ process.exit(1);
72
+ }
73
+ });
74
+ // Stop command (K722)
75
+ commander_1.program
76
+ .command('stop')
77
+ .description('Stop the Episoda daemon')
78
+ .option('--force', 'Force kill daemon without graceful shutdown')
79
+ .action(async (options) => {
80
+ try {
81
+ await (0, stop_1.stopCommand)(options);
82
+ }
83
+ catch (error) {
84
+ output_1.status.error(`Stop failed: ${error instanceof Error ? error.message : String(error)}`);
85
+ process.exit(1);
86
+ }
87
+ });
88
+ // Disconnect command (alias for stop)
89
+ commander_1.program
90
+ .command('disconnect')
91
+ .description('Disconnect from episoda.dev (alias for stop)')
92
+ .action(async () => {
93
+ try {
94
+ await (0, stop_1.stopCommand)();
95
+ }
96
+ catch (error) {
97
+ output_1.status.error(`Disconnect failed: ${error instanceof Error ? error.message : String(error)}`);
98
+ process.exit(1);
99
+ }
100
+ });
101
+ commander_1.program.parse();
102
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * IPC Client - Used by CLI commands
3
+ *
4
+ * Sends commands to daemon via Unix domain socket.
5
+ * Handles request/response communication.
6
+ *
7
+ * Socket location: ~/.episoda/daemon.sock
8
+ */
9
+ export interface IPCRequest {
10
+ id: string;
11
+ command: string;
12
+ params?: any;
13
+ }
14
+ export interface IPCResponse {
15
+ id: string;
16
+ success: boolean;
17
+ data?: any;
18
+ error?: string;
19
+ }
20
+ /**
21
+ * Send command to daemon
22
+ *
23
+ * Connects to daemon socket, sends command, waits for response.
24
+ *
25
+ * @param command Command name
26
+ * @param params Command parameters
27
+ * @param timeout Timeout in milliseconds (default: 15000)
28
+ * @returns Response data
29
+ * @throws Error if daemon not running or command fails
30
+ */
31
+ export declare function sendCommand(command: string, params?: any, timeout?: number): Promise<any>;
32
+ /**
33
+ * Check if daemon is reachable via IPC
34
+ *
35
+ * @returns true if daemon is running and responding
36
+ */
37
+ export declare function isDaemonReachable(): Promise<boolean>;
38
+ /**
39
+ * Add project to daemon
40
+ *
41
+ * EP734: Now blocking - waits for WebSocket connection to complete
42
+ *
43
+ * @param projectId Supabase project ID
44
+ * @param projectPath Absolute path to project
45
+ * @returns Connection result with success/error info
46
+ */
47
+ export declare function addProject(projectId: string, projectPath: string): Promise<{
48
+ success: boolean;
49
+ connected: boolean;
50
+ error?: string;
51
+ }>;
52
+ /**
53
+ * Remove project from daemon
54
+ *
55
+ * @param projectPath Absolute path to project
56
+ */
57
+ export declare function removeProject(projectPath: string): Promise<void>;
58
+ /**
59
+ * Get daemon status
60
+ *
61
+ * EP738: Added hostname, platform, arch for status command (HTTP server removed)
62
+ *
63
+ * @returns Status information including connected projects and device info
64
+ */
65
+ export declare function getStatus(): Promise<{
66
+ running: boolean;
67
+ machineId: string;
68
+ deviceId?: string;
69
+ hostname: string;
70
+ platform: string;
71
+ arch: string;
72
+ projects: Array<{
73
+ id: string;
74
+ path: string;
75
+ name: string;
76
+ connected: boolean;
77
+ }>;
78
+ }>;
79
+ /**
80
+ * Request daemon to connect to a project's WebSocket
81
+ *
82
+ * @param projectPath Absolute path to project
83
+ */
84
+ export declare function connectProject(projectPath: string): Promise<void>;
85
+ /**
86
+ * Request daemon to disconnect from a project's WebSocket
87
+ *
88
+ * @param projectPath Absolute path to project
89
+ */
90
+ export declare function disconnectProject(projectPath: string): Promise<void>;
91
+ /**
92
+ * Request daemon shutdown
93
+ */
94
+ export declare function shutdownDaemon(): Promise<void>;
95
+ //# sourceMappingURL=ipc-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ipc-client.d.ts","sourceRoot":"","sources":["../../src/ipc/ipc-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,GAAG,CAAA;CACb;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,CAAC,EAAE,GAAG,CAAA;IACV,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,GAAG,EACZ,OAAO,GAAE,MAAwB,GAChC,OAAO,CAAC,GAAG,CAAC,CA2Ed;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAO1D;AAED;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAChF,OAAO,EAAE,OAAO,CAAA;IAChB,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAC,CAGD;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtE;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC;IACzC,OAAO,EAAE,OAAO,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,KAAK,CAAC;QACd,EAAE,EAAE,MAAM,CAAA;QACV,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,SAAS,EAAE,OAAO,CAAA;KACnB,CAAC,CAAA;CACH,CAAC,CAED;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvE;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1E;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAEpD"}
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ /**
3
+ * IPC Client - Used by CLI commands
4
+ *
5
+ * Sends commands to daemon via Unix domain socket.
6
+ * Handles request/response communication.
7
+ *
8
+ * Socket location: ~/.episoda/daemon.sock
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.sendCommand = sendCommand;
45
+ exports.isDaemonReachable = isDaemonReachable;
46
+ exports.addProject = addProject;
47
+ exports.removeProject = removeProject;
48
+ exports.getStatus = getStatus;
49
+ exports.connectProject = connectProject;
50
+ exports.disconnectProject = disconnectProject;
51
+ exports.shutdownDaemon = shutdownDaemon;
52
+ const net = __importStar(require("net"));
53
+ const path = __importStar(require("path"));
54
+ const crypto = __importStar(require("crypto"));
55
+ const core_1 = require("../core");
56
+ const getSocketPath = () => path.join((0, core_1.getConfigDir)(), 'daemon.sock');
57
+ const DEFAULT_TIMEOUT = 15000; // 15 seconds (EP606: increased for device registration)
58
+ /**
59
+ * Send command to daemon
60
+ *
61
+ * Connects to daemon socket, sends command, waits for response.
62
+ *
63
+ * @param command Command name
64
+ * @param params Command parameters
65
+ * @param timeout Timeout in milliseconds (default: 15000)
66
+ * @returns Response data
67
+ * @throws Error if daemon not running or command fails
68
+ */
69
+ async function sendCommand(command, params, timeout = DEFAULT_TIMEOUT) {
70
+ return new Promise((resolve, reject) => {
71
+ const socket = net.createConnection(getSocketPath());
72
+ const requestId = crypto.randomUUID();
73
+ let buffer = '';
74
+ let timeoutHandle;
75
+ // Set timeout
76
+ timeoutHandle = setTimeout(() => {
77
+ socket.destroy();
78
+ reject(new Error(`Command timed out after ${timeout}ms`));
79
+ }, timeout);
80
+ socket.on('connect', () => {
81
+ // Send request
82
+ const request = {
83
+ id: requestId,
84
+ command,
85
+ params,
86
+ };
87
+ socket.write(JSON.stringify(request) + '\n');
88
+ });
89
+ socket.on('data', (chunk) => {
90
+ buffer += chunk.toString();
91
+ // Check for complete response (delimited by newline)
92
+ const newlineIndex = buffer.indexOf('\n');
93
+ if (newlineIndex === -1)
94
+ return;
95
+ // Extract response
96
+ const message = buffer.slice(0, newlineIndex);
97
+ try {
98
+ const response = JSON.parse(message);
99
+ // Verify response ID matches
100
+ if (response.id !== requestId) {
101
+ reject(new Error('Response ID mismatch'));
102
+ return;
103
+ }
104
+ clearTimeout(timeoutHandle);
105
+ socket.end();
106
+ if (response.success) {
107
+ resolve(response.data);
108
+ }
109
+ else {
110
+ reject(new Error(response.error || 'Command failed'));
111
+ }
112
+ }
113
+ catch (error) {
114
+ clearTimeout(timeoutHandle);
115
+ socket.end();
116
+ reject(new Error('Invalid response from daemon'));
117
+ }
118
+ });
119
+ socket.on('error', (error) => {
120
+ clearTimeout(timeoutHandle);
121
+ // Check for common errors
122
+ if (error.code === 'ENOENT' || error.code === 'ECONNREFUSED') {
123
+ reject(new Error('Daemon is not running. Start it with: episoda dev'));
124
+ }
125
+ else {
126
+ reject(error);
127
+ }
128
+ });
129
+ socket.on('timeout', () => {
130
+ clearTimeout(timeoutHandle);
131
+ socket.destroy();
132
+ reject(new Error('Connection timeout'));
133
+ });
134
+ });
135
+ }
136
+ /**
137
+ * Check if daemon is reachable via IPC
138
+ *
139
+ * @returns true if daemon is running and responding
140
+ */
141
+ async function isDaemonReachable() {
142
+ try {
143
+ await sendCommand('ping', {}, 1000);
144
+ return true;
145
+ }
146
+ catch (error) {
147
+ return false;
148
+ }
149
+ }
150
+ /**
151
+ * Add project to daemon
152
+ *
153
+ * EP734: Now blocking - waits for WebSocket connection to complete
154
+ *
155
+ * @param projectId Supabase project ID
156
+ * @param projectPath Absolute path to project
157
+ * @returns Connection result with success/error info
158
+ */
159
+ async function addProject(projectId, projectPath) {
160
+ // EP734: Increased timeout to 30s to allow for WebSocket connection
161
+ return await sendCommand('add-project', { projectId, projectPath }, 30000);
162
+ }
163
+ /**
164
+ * Remove project from daemon
165
+ *
166
+ * @param projectPath Absolute path to project
167
+ */
168
+ async function removeProject(projectPath) {
169
+ await sendCommand('remove-project', { projectPath });
170
+ }
171
+ /**
172
+ * Get daemon status
173
+ *
174
+ * EP738: Added hostname, platform, arch for status command (HTTP server removed)
175
+ *
176
+ * @returns Status information including connected projects and device info
177
+ */
178
+ async function getStatus() {
179
+ return await sendCommand('status');
180
+ }
181
+ /**
182
+ * Request daemon to connect to a project's WebSocket
183
+ *
184
+ * @param projectPath Absolute path to project
185
+ */
186
+ async function connectProject(projectPath) {
187
+ await sendCommand('connect-project', { projectPath });
188
+ }
189
+ /**
190
+ * Request daemon to disconnect from a project's WebSocket
191
+ *
192
+ * @param projectPath Absolute path to project
193
+ */
194
+ async function disconnectProject(projectPath) {
195
+ await sendCommand('disconnect-project', { projectPath });
196
+ }
197
+ /**
198
+ * Request daemon shutdown
199
+ */
200
+ async function shutdownDaemon() {
201
+ await sendCommand('shutdown', {}, 2000);
202
+ }
203
+ // EP734: Removed getConnectionStatus - no longer needed with blocking add-project
204
+ //# sourceMappingURL=ipc-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ipc-client.js","sourceRoot":"","sources":["../../src/ipc/ipc-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * IPC Server - Runs in daemon process
3
+ *
4
+ * Listens for commands from CLI via Unix domain socket.
5
+ * Handles command routing and response sending.
6
+ *
7
+ * Socket location: ~/.episoda/daemon.sock
8
+ */
9
+ export interface IPCRequest {
10
+ id: string;
11
+ command: string;
12
+ params?: any;
13
+ }
14
+ export interface IPCResponse {
15
+ id: string;
16
+ success: boolean;
17
+ data?: any;
18
+ error?: string;
19
+ }
20
+ export type CommandHandler = (params: any) => Promise<any>;
21
+ /**
22
+ * IPC Server
23
+ *
24
+ * Listens on Unix socket for CLI commands.
25
+ */
26
+ export declare class IPCServer {
27
+ private server;
28
+ private handlers;
29
+ /**
30
+ * Register a command handler
31
+ *
32
+ * @param command Command name
33
+ * @param handler Async function to handle command
34
+ */
35
+ on(command: string, handler: CommandHandler): void;
36
+ /**
37
+ * Start the IPC server
38
+ *
39
+ * Creates Unix socket and listens for connections.
40
+ */
41
+ start(): Promise<void>;
42
+ /**
43
+ * Stop the IPC server
44
+ */
45
+ stop(): Promise<void>;
46
+ /**
47
+ * Handle incoming client connection
48
+ */
49
+ private handleConnection;
50
+ /**
51
+ * Handle IPC request
52
+ */
53
+ private handleRequest;
54
+ }
55
+ //# sourceMappingURL=ipc-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ipc-server.d.ts","sourceRoot":"","sources":["../../src/ipc/ipc-server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,GAAG,CAAA;CACb;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,CAAC,EAAE,GAAG,CAAA;IACV,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;AAE1D;;;;GAIG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,QAAQ,CAAoC;IAEpD;;;;;OAKG;IACH,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI;IAIlD;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA6B5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAe3B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAmCxB;;OAEG;YACW,aAAa;CA0B5B"}