@hexidecibel/companion 0.0.1
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/dist/__tests__/task-parser.test.d.ts +2 -0
- package/dist/__tests__/task-parser.test.d.ts.map +1 -0
- package/dist/__tests__/task-parser.test.js +79 -0
- package/dist/__tests__/task-parser.test.js.map +1 -0
- package/dist/anthropic-usage.d.ts +5 -0
- package/dist/anthropic-usage.d.ts.map +1 -0
- package/dist/anthropic-usage.js +112 -0
- package/dist/anthropic-usage.js.map +1 -0
- package/dist/cert-generator.d.ts +15 -0
- package/dist/cert-generator.d.ts.map +1 -0
- package/dist/cert-generator.js +298 -0
- package/dist/cert-generator.js.map +1 -0
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +122 -0
- package/dist/config.js.map +1 -0
- package/dist/encryption.d.ts +28 -0
- package/dist/encryption.d.ts.map +1 -0
- package/dist/encryption.js +95 -0
- package/dist/encryption.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +211 -0
- package/dist/index.js.map +1 -0
- package/dist/input-injector.d.ts +21 -0
- package/dist/input-injector.d.ts.map +1 -0
- package/dist/input-injector.js +126 -0
- package/dist/input-injector.js.map +1 -0
- package/dist/mdns.d.ts +11 -0
- package/dist/mdns.d.ts.map +1 -0
- package/dist/mdns.js +93 -0
- package/dist/mdns.js.map +1 -0
- package/dist/parser.d.ts +43 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +800 -0
- package/dist/parser.js.map +1 -0
- package/dist/push.d.ts +38 -0
- package/dist/push.d.ts.map +1 -0
- package/dist/push.js +359 -0
- package/dist/push.js.map +1 -0
- package/dist/qr-server.d.ts +13 -0
- package/dist/qr-server.d.ts.map +1 -0
- package/dist/qr-server.js +421 -0
- package/dist/qr-server.js.map +1 -0
- package/dist/scaffold/generator.d.ts +11 -0
- package/dist/scaffold/generator.d.ts.map +1 -0
- package/dist/scaffold/generator.js +206 -0
- package/dist/scaffold/generator.js.map +1 -0
- package/dist/scaffold/templates/index.d.ts +5 -0
- package/dist/scaffold/templates/index.d.ts.map +1 -0
- package/dist/scaffold/templates/index.js +22 -0
- package/dist/scaffold/templates/index.js.map +1 -0
- package/dist/scaffold/templates/node-express.d.ts +3 -0
- package/dist/scaffold/templates/node-express.d.ts.map +1 -0
- package/dist/scaffold/templates/node-express.js +218 -0
- package/dist/scaffold/templates/node-express.js.map +1 -0
- package/dist/scaffold/templates/python-fastapi.d.ts +3 -0
- package/dist/scaffold/templates/python-fastapi.d.ts.map +1 -0
- package/dist/scaffold/templates/python-fastapi.js +302 -0
- package/dist/scaffold/templates/python-fastapi.js.map +1 -0
- package/dist/scaffold/templates/react-mui-website.d.ts +3 -0
- package/dist/scaffold/templates/react-mui-website.d.ts.map +1 -0
- package/dist/scaffold/templates/react-mui-website.js +405 -0
- package/dist/scaffold/templates/react-mui-website.js.map +1 -0
- package/dist/scaffold/templates/react-typescript.d.ts +3 -0
- package/dist/scaffold/templates/react-typescript.d.ts.map +1 -0
- package/dist/scaffold/templates/react-typescript.js +275 -0
- package/dist/scaffold/templates/react-typescript.js.map +1 -0
- package/dist/scaffold/types.d.ts +55 -0
- package/dist/scaffold/types.d.ts.map +1 -0
- package/dist/scaffold/types.js +3 -0
- package/dist/scaffold/types.js.map +1 -0
- package/dist/subagent-watcher.d.ts +24 -0
- package/dist/subagent-watcher.d.ts.map +1 -0
- package/dist/subagent-watcher.js +307 -0
- package/dist/subagent-watcher.js.map +1 -0
- package/dist/tls.d.ts +10 -0
- package/dist/tls.d.ts.map +1 -0
- package/dist/tls.js +77 -0
- package/dist/tls.js.map +1 -0
- package/dist/tmux-manager.d.ts +71 -0
- package/dist/tmux-manager.d.ts.map +1 -0
- package/dist/tmux-manager.js +243 -0
- package/dist/tmux-manager.js.map +1 -0
- package/dist/tool-config.d.ts +33 -0
- package/dist/tool-config.d.ts.map +1 -0
- package/dist/tool-config.js +211 -0
- package/dist/tool-config.js.map +1 -0
- package/dist/types.d.ts +218 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/watcher.d.ts +63 -0
- package/dist/watcher.d.ts.map +1 -0
- package/dist/watcher.js +596 -0
- package/dist/watcher.js.map +1 -0
- package/dist/watcher.test.d.ts +2 -0
- package/dist/watcher.test.d.ts.map +1 -0
- package/dist/watcher.test.js +110 -0
- package/dist/watcher.test.js.map +1 -0
- package/dist/websocket.d.ts +62 -0
- package/dist/websocket.d.ts.map +1 -0
- package/dist/websocket.js +1695 -0
- package/dist/websocket.js.map +1 -0
- package/package.json +71 -0
- package/scripts/build.sh +23 -0
- package/scripts/install-remote.sh +18 -0
- package/scripts/install.sh +558 -0
- package/scripts/uninstall.sh +113 -0
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.createQRRequestHandler = createQRRequestHandler;
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const os = __importStar(require("os"));
|
|
43
|
+
const qrcode_1 = __importDefault(require("qrcode"));
|
|
44
|
+
/**
|
|
45
|
+
* Get the server's local IP address (non-loopback)
|
|
46
|
+
*/
|
|
47
|
+
function getLocalIP() {
|
|
48
|
+
const interfaces = os.networkInterfaces();
|
|
49
|
+
for (const name of Object.keys(interfaces)) {
|
|
50
|
+
const netInterface = interfaces[name];
|
|
51
|
+
if (!netInterface)
|
|
52
|
+
continue;
|
|
53
|
+
for (const iface of netInterface) {
|
|
54
|
+
// Skip loopback and non-IPv4
|
|
55
|
+
if (iface.family === 'IPv4' && !iface.internal) {
|
|
56
|
+
return iface.address;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return 'localhost';
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get content type for file extension
|
|
64
|
+
*/
|
|
65
|
+
function getContentType(filePath) {
|
|
66
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
67
|
+
const types = {
|
|
68
|
+
'.html': 'text/html',
|
|
69
|
+
'.css': 'text/css',
|
|
70
|
+
'.js': 'application/javascript',
|
|
71
|
+
'.json': 'application/json',
|
|
72
|
+
'.png': 'image/png',
|
|
73
|
+
'.jpg': 'image/jpeg',
|
|
74
|
+
'.jpeg': 'image/jpeg',
|
|
75
|
+
'.gif': 'image/gif',
|
|
76
|
+
'.svg': 'image/svg+xml',
|
|
77
|
+
'.ico': 'image/x-icon',
|
|
78
|
+
};
|
|
79
|
+
return types[ext] || 'text/plain';
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Find the web directory (handles both dev and installed paths)
|
|
83
|
+
*/
|
|
84
|
+
function findWebDir() {
|
|
85
|
+
// Try built Vite output first (web/dist/), then fall back to source web/
|
|
86
|
+
const bases = [
|
|
87
|
+
path.join(__dirname, '../../web'), // From dist/
|
|
88
|
+
path.join(__dirname, '../../../web'), // From dist/ in installed location
|
|
89
|
+
path.join(process.cwd(), '../web'), // From daemon directory
|
|
90
|
+
path.join(process.cwd(), 'web'), // From project root
|
|
91
|
+
];
|
|
92
|
+
// Prefer web/dist/ (Vite build output)
|
|
93
|
+
for (const base of bases) {
|
|
94
|
+
const distDir = path.join(base, 'dist');
|
|
95
|
+
if (fs.existsSync(path.join(distDir, 'index.html'))) {
|
|
96
|
+
return distDir;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Fall back to web/ root (old vanilla client)
|
|
100
|
+
for (const dir of bases) {
|
|
101
|
+
if (fs.existsSync(path.join(dir, 'index.html'))) {
|
|
102
|
+
return dir;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Create an HTTP request handler that serves QR code at /qr and web client at /web
|
|
109
|
+
*/
|
|
110
|
+
function createQRRequestHandler(config) {
|
|
111
|
+
const webDir = findWebDir();
|
|
112
|
+
if (webDir) {
|
|
113
|
+
console.log(`Web client: Serving from ${webDir}`);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
console.log('Web client: Not found (web/ directory missing)');
|
|
117
|
+
}
|
|
118
|
+
return async (req, res) => {
|
|
119
|
+
// Handle CORS preflight
|
|
120
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
121
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
|
122
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
|
123
|
+
if (req.method === 'OPTIONS') {
|
|
124
|
+
res.writeHead(204);
|
|
125
|
+
res.end();
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const fullUrl = req.url || '/';
|
|
129
|
+
const [urlPath, queryString] = fullUrl.split('?');
|
|
130
|
+
const params = new URLSearchParams(queryString || '');
|
|
131
|
+
// HTTP image upload endpoint - more reliable than WebSocket for large payloads
|
|
132
|
+
if (urlPath === '/upload' && req.method === 'POST') {
|
|
133
|
+
// Verify auth token
|
|
134
|
+
const authHeader = req.headers['authorization'];
|
|
135
|
+
const token = authHeader?.replace('Bearer ', '');
|
|
136
|
+
if (token !== config.token) {
|
|
137
|
+
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
138
|
+
res.end(JSON.stringify({ success: false, error: 'Unauthorized' }));
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
// Read request body (raw binary image data)
|
|
142
|
+
const chunks = [];
|
|
143
|
+
req.on('data', (chunk) => chunks.push(chunk));
|
|
144
|
+
req.on('end', () => {
|
|
145
|
+
try {
|
|
146
|
+
const body = Buffer.concat(chunks);
|
|
147
|
+
const contentType = req.headers['content-type'] || 'image/jpeg';
|
|
148
|
+
const ext = contentType.includes('png') ? 'png' : 'jpg';
|
|
149
|
+
const filename = `companion-${Date.now()}.${ext}`;
|
|
150
|
+
const filepath = path.join(os.tmpdir(), filename);
|
|
151
|
+
fs.writeFileSync(filepath, body);
|
|
152
|
+
console.log(`HTTP upload: ${filepath} (${body.length} bytes)`);
|
|
153
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
154
|
+
res.end(JSON.stringify({ success: true, filepath }));
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
console.error('HTTP upload error:', err);
|
|
158
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
159
|
+
res.end(JSON.stringify({ success: false, error: 'Upload failed' }));
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
// Web client routes - public access, security via WebSocket token
|
|
165
|
+
if (urlPath.startsWith('/web')) {
|
|
166
|
+
if (!webDir) {
|
|
167
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
168
|
+
res.end('Web client not found. Make sure web/ directory exists.');
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
// Determine file to serve
|
|
172
|
+
let filePath = urlPath.replace('/web', '') || '/index.html';
|
|
173
|
+
if (filePath === '/' || filePath === '') {
|
|
174
|
+
filePath = '/index.html';
|
|
175
|
+
}
|
|
176
|
+
const fullPath = path.join(webDir, filePath);
|
|
177
|
+
// Security: prevent directory traversal
|
|
178
|
+
if (!fullPath.startsWith(webDir)) {
|
|
179
|
+
res.writeHead(403, { 'Content-Type': 'text/plain' });
|
|
180
|
+
res.end('Forbidden');
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
// SPA fallback: if file not found and not a static asset, serve index.html
|
|
185
|
+
let servePath = fullPath;
|
|
186
|
+
if (!fs.existsSync(fullPath)) {
|
|
187
|
+
const ext = path.extname(fullPath);
|
|
188
|
+
if (ext && ext !== '.html') {
|
|
189
|
+
// Static asset not found — genuine 404
|
|
190
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
191
|
+
res.end('Not Found');
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
// Route path — serve index.html for client-side routing
|
|
195
|
+
servePath = path.join(webDir, 'index.html');
|
|
196
|
+
if (!fs.existsSync(servePath)) {
|
|
197
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
198
|
+
res.end('Not Found');
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const content = fs.readFileSync(servePath);
|
|
203
|
+
const contentType = getContentType(servePath);
|
|
204
|
+
res.writeHead(200, {
|
|
205
|
+
'Content-Type': contentType,
|
|
206
|
+
'Content-Length': content.length,
|
|
207
|
+
'Cache-Control': 'no-cache',
|
|
208
|
+
});
|
|
209
|
+
res.end(content);
|
|
210
|
+
}
|
|
211
|
+
catch (err) {
|
|
212
|
+
console.error('Error serving web file:', err);
|
|
213
|
+
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
214
|
+
res.end('Internal Server Error');
|
|
215
|
+
}
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
// QR and JSON endpoints require token auth via query param
|
|
219
|
+
const url = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);
|
|
220
|
+
const queryToken = url.searchParams.get('token');
|
|
221
|
+
const isAuthed = queryToken === config.token;
|
|
222
|
+
if (urlPath === '/qr' || urlPath === '/qr.png') {
|
|
223
|
+
if (!isAuthed) {
|
|
224
|
+
res.writeHead(401, { 'Content-Type': 'text/plain' });
|
|
225
|
+
res.end('Unauthorized - token required');
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
try {
|
|
229
|
+
const qrConfig = {
|
|
230
|
+
host: getLocalIP(),
|
|
231
|
+
port: config.port,
|
|
232
|
+
token: config.token,
|
|
233
|
+
tls: config.tls,
|
|
234
|
+
};
|
|
235
|
+
const qrData = JSON.stringify(qrConfig);
|
|
236
|
+
const qrBuffer = await qrcode_1.default.toBuffer(qrData, {
|
|
237
|
+
type: 'png',
|
|
238
|
+
width: 400,
|
|
239
|
+
margin: 2,
|
|
240
|
+
color: {
|
|
241
|
+
dark: '#000000',
|
|
242
|
+
light: '#ffffff',
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
res.writeHead(200, {
|
|
246
|
+
'Content-Type': 'image/png',
|
|
247
|
+
'Content-Length': qrBuffer.length,
|
|
248
|
+
'Cache-Control': 'no-cache',
|
|
249
|
+
});
|
|
250
|
+
res.end(qrBuffer);
|
|
251
|
+
}
|
|
252
|
+
catch (err) {
|
|
253
|
+
console.error('Error generating QR code:', err);
|
|
254
|
+
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
255
|
+
res.end('Error generating QR code');
|
|
256
|
+
}
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
if (urlPath === '/qr.json') {
|
|
260
|
+
if (!isAuthed) {
|
|
261
|
+
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
262
|
+
res.end(JSON.stringify({ error: 'Unauthorized - token required' }));
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
const qrConfig = {
|
|
266
|
+
host: getLocalIP(),
|
|
267
|
+
port: config.port,
|
|
268
|
+
token: config.token,
|
|
269
|
+
tls: config.tls,
|
|
270
|
+
};
|
|
271
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
272
|
+
res.end(JSON.stringify(qrConfig, null, 2));
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
if (urlPath === '/') {
|
|
276
|
+
// HTML page with token gate - must enter token before seeing QR
|
|
277
|
+
const webClientPath = webDir ? '/web' : '';
|
|
278
|
+
const html = `<!DOCTYPE html>
|
|
279
|
+
<html>
|
|
280
|
+
<head>
|
|
281
|
+
<title>Companion Setup</title>
|
|
282
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
283
|
+
<style>
|
|
284
|
+
body {
|
|
285
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
286
|
+
background: #111827;
|
|
287
|
+
color: #f3f4f6;
|
|
288
|
+
min-height: 100vh;
|
|
289
|
+
display: flex;
|
|
290
|
+
flex-direction: column;
|
|
291
|
+
align-items: center;
|
|
292
|
+
justify-content: center;
|
|
293
|
+
margin: 0;
|
|
294
|
+
padding: 20px;
|
|
295
|
+
}
|
|
296
|
+
h1 { margin-bottom: 8px; }
|
|
297
|
+
p { color: #9ca3af; margin-bottom: 24px; }
|
|
298
|
+
img {
|
|
299
|
+
border-radius: 16px;
|
|
300
|
+
background: white;
|
|
301
|
+
padding: 16px;
|
|
302
|
+
}
|
|
303
|
+
.info {
|
|
304
|
+
margin-top: 24px;
|
|
305
|
+
background: #1f2937;
|
|
306
|
+
padding: 16px 24px;
|
|
307
|
+
border-radius: 12px;
|
|
308
|
+
font-size: 14px;
|
|
309
|
+
}
|
|
310
|
+
.info p { margin-bottom: 8px; }
|
|
311
|
+
.info code { color: #3b82f6; }
|
|
312
|
+
.web-link {
|
|
313
|
+
display: inline-block;
|
|
314
|
+
margin-top: 24px;
|
|
315
|
+
padding: 14px 28px;
|
|
316
|
+
background: #3b82f6;
|
|
317
|
+
color: white;
|
|
318
|
+
text-decoration: none;
|
|
319
|
+
border-radius: 10px;
|
|
320
|
+
font-weight: 600;
|
|
321
|
+
transition: background 0.2s;
|
|
322
|
+
}
|
|
323
|
+
.web-link:hover { background: #2563eb; }
|
|
324
|
+
.token-form {
|
|
325
|
+
background: #1f2937;
|
|
326
|
+
padding: 32px;
|
|
327
|
+
border-radius: 16px;
|
|
328
|
+
max-width: 400px;
|
|
329
|
+
width: 100%;
|
|
330
|
+
text-align: center;
|
|
331
|
+
}
|
|
332
|
+
.token-input {
|
|
333
|
+
width: 100%;
|
|
334
|
+
padding: 12px 16px;
|
|
335
|
+
border: 1px solid #374151;
|
|
336
|
+
border-radius: 8px;
|
|
337
|
+
background: #111827;
|
|
338
|
+
color: #f3f4f6;
|
|
339
|
+
font-size: 16px;
|
|
340
|
+
margin-bottom: 16px;
|
|
341
|
+
box-sizing: border-box;
|
|
342
|
+
font-family: monospace;
|
|
343
|
+
}
|
|
344
|
+
.token-input:focus { outline: none; border-color: #3b82f6; }
|
|
345
|
+
.token-btn {
|
|
346
|
+
width: 100%;
|
|
347
|
+
padding: 12px;
|
|
348
|
+
background: #3b82f6;
|
|
349
|
+
color: white;
|
|
350
|
+
border: none;
|
|
351
|
+
border-radius: 8px;
|
|
352
|
+
font-size: 16px;
|
|
353
|
+
font-weight: 600;
|
|
354
|
+
cursor: pointer;
|
|
355
|
+
}
|
|
356
|
+
.token-btn:hover { background: #2563eb; }
|
|
357
|
+
.error { color: #ef4444; font-size: 14px; margin-bottom: 12px; }
|
|
358
|
+
#auth-section { display: block; }
|
|
359
|
+
#qr-section { display: none; }
|
|
360
|
+
</style>
|
|
361
|
+
</head>
|
|
362
|
+
<body>
|
|
363
|
+
<h1>Companion</h1>
|
|
364
|
+
|
|
365
|
+
<div id="auth-section">
|
|
366
|
+
<p>Enter your token to access setup</p>
|
|
367
|
+
<div class="token-form">
|
|
368
|
+
<input type="password" id="token" class="token-input" placeholder="Enter token..." autofocus>
|
|
369
|
+
<div id="error" class="error" style="display:none"></div>
|
|
370
|
+
<button class="token-btn" onclick="authenticate()">Authenticate</button>
|
|
371
|
+
</div>
|
|
372
|
+
<div class="info">
|
|
373
|
+
<p>Server: <code>${getLocalIP()}:${config.port}</code></p>
|
|
374
|
+
</div>
|
|
375
|
+
</div>
|
|
376
|
+
|
|
377
|
+
<div id="qr-section">
|
|
378
|
+
<p>Scan this QR code with the app to connect</p>
|
|
379
|
+
<img id="qr-img" alt="QR Code" width="300" height="300">
|
|
380
|
+
<div class="info">
|
|
381
|
+
<p>Server: <code>${getLocalIP()}:${config.port}</code></p>
|
|
382
|
+
<p>TLS: <code>${config.tls ? 'Enabled' : 'Disabled'}</code></p>
|
|
383
|
+
</div>
|
|
384
|
+
${webClientPath ? `<a href="${webClientPath}" class="web-link">Open Web Client</a>` : ''}
|
|
385
|
+
</div>
|
|
386
|
+
|
|
387
|
+
<script>
|
|
388
|
+
function authenticate() {
|
|
389
|
+
var token = document.getElementById('token').value;
|
|
390
|
+
if (!token) return;
|
|
391
|
+
// Test by fetching the QR image with the token
|
|
392
|
+
fetch('/qr.png?token=' + encodeURIComponent(token))
|
|
393
|
+
.then(function(res) {
|
|
394
|
+
if (res.ok) {
|
|
395
|
+
document.getElementById('auth-section').style.display = 'none';
|
|
396
|
+
document.getElementById('qr-section').style.display = 'flex';
|
|
397
|
+
document.getElementById('qr-section').style.flexDirection = 'column';
|
|
398
|
+
document.getElementById('qr-section').style.alignItems = 'center';
|
|
399
|
+
document.getElementById('qr-img').src = '/qr.png?token=' + encodeURIComponent(token);
|
|
400
|
+
} else {
|
|
401
|
+
document.getElementById('error').textContent = 'Invalid token';
|
|
402
|
+
document.getElementById('error').style.display = 'block';
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
document.getElementById('token').addEventListener('keydown', function(e) {
|
|
407
|
+
if (e.key === 'Enter') authenticate();
|
|
408
|
+
});
|
|
409
|
+
</script>
|
|
410
|
+
</body>
|
|
411
|
+
</html>`;
|
|
412
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
413
|
+
res.end(html);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
// 404 for other paths
|
|
417
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
418
|
+
res.end('Not Found');
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
//# sourceMappingURL=qr-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qr-server.js","sourceRoot":"","sources":["../src/qr-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ProjectConfig, ScaffoldProgress, ScaffoldResult } from './types';
|
|
2
|
+
type ProgressCallback = (progress: ScaffoldProgress) => void;
|
|
3
|
+
export declare function scaffoldProject(config: ProjectConfig, onProgress?: ProgressCallback): Promise<ScaffoldResult>;
|
|
4
|
+
export declare function previewScaffold(config: ProjectConfig): Promise<{
|
|
5
|
+
files: string[];
|
|
6
|
+
projectPath: string;
|
|
7
|
+
} | {
|
|
8
|
+
error: string;
|
|
9
|
+
}>;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/scaffold/generator.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,cAAc,EAAiB,MAAM,SAAS,CAAC;AAgBzF,KAAK,gBAAgB,GAAG,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAoB7D,wBAAsB,eAAe,CACnC,MAAM,EAAE,aAAa,EACrB,UAAU,CAAC,EAAE,gBAAgB,GAC5B,OAAO,CAAC,cAAc,CAAC,CA2IzB;AAGD,wBAAsB,eAAe,CACnC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAUvE"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.scaffoldProject = scaffoldProject;
|
|
37
|
+
exports.previewScaffold = previewScaffold;
|
|
38
|
+
const fs = __importStar(require("fs/promises"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const os = __importStar(require("os"));
|
|
41
|
+
const child_process_1 = require("child_process");
|
|
42
|
+
const util_1 = require("util");
|
|
43
|
+
const templates_1 = require("./templates");
|
|
44
|
+
// Expand ~ to home directory
|
|
45
|
+
function expandPath(p) {
|
|
46
|
+
if (p.startsWith('~/')) {
|
|
47
|
+
return path.join(os.homedir(), p.slice(2));
|
|
48
|
+
}
|
|
49
|
+
if (p === '~') {
|
|
50
|
+
return os.homedir();
|
|
51
|
+
}
|
|
52
|
+
return p;
|
|
53
|
+
}
|
|
54
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
55
|
+
// Replace template variables with actual values
|
|
56
|
+
function interpolate(template, variables) {
|
|
57
|
+
let result = template;
|
|
58
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
59
|
+
result = result.replace(new RegExp(`\\{\\{${key}\\}\\}`, 'g'), value);
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
// Convert project name to valid identifier (for package names, etc.)
|
|
64
|
+
function toValidName(name) {
|
|
65
|
+
return name
|
|
66
|
+
.toLowerCase()
|
|
67
|
+
.replace(/[^a-z0-9-]/g, '-')
|
|
68
|
+
.replace(/-+/g, '-')
|
|
69
|
+
.replace(/^-|-$/g, '');
|
|
70
|
+
}
|
|
71
|
+
async function scaffoldProject(config, onProgress) {
|
|
72
|
+
const template = (0, templates_1.getTemplate)(config.stackId);
|
|
73
|
+
if (!template) {
|
|
74
|
+
return {
|
|
75
|
+
success: false,
|
|
76
|
+
projectPath: config.location,
|
|
77
|
+
filesCreated: [],
|
|
78
|
+
error: `Unknown template: ${config.stackId}`,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const projectPath = path.join(expandPath(config.location), toValidName(config.name));
|
|
82
|
+
const filesCreated = [];
|
|
83
|
+
const variables = {
|
|
84
|
+
projectName: toValidName(config.name),
|
|
85
|
+
projectDescription: config.description || `A ${template.name} project`,
|
|
86
|
+
};
|
|
87
|
+
try {
|
|
88
|
+
// Step 1: Create project directory
|
|
89
|
+
onProgress?.({
|
|
90
|
+
step: 'Creating project directory',
|
|
91
|
+
progress: 5,
|
|
92
|
+
complete: false,
|
|
93
|
+
});
|
|
94
|
+
await fs.mkdir(projectPath, { recursive: true });
|
|
95
|
+
// Step 2: Create files from template
|
|
96
|
+
const totalFiles = template.files.length;
|
|
97
|
+
for (let i = 0; i < template.files.length; i++) {
|
|
98
|
+
const file = template.files[i];
|
|
99
|
+
const filePath = path.join(projectPath, interpolate(file.path, variables));
|
|
100
|
+
const fileContent = interpolate(file.template, variables);
|
|
101
|
+
onProgress?.({
|
|
102
|
+
step: 'Creating files',
|
|
103
|
+
detail: file.path,
|
|
104
|
+
progress: 10 + Math.floor((i / totalFiles) * 50),
|
|
105
|
+
complete: false,
|
|
106
|
+
});
|
|
107
|
+
// Ensure directory exists
|
|
108
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
109
|
+
await fs.writeFile(filePath, fileContent, 'utf-8');
|
|
110
|
+
filesCreated.push(file.path);
|
|
111
|
+
}
|
|
112
|
+
// Step 3: Initialize git if requested
|
|
113
|
+
if (config.options.initGit) {
|
|
114
|
+
onProgress?.({
|
|
115
|
+
step: 'Initializing git repository',
|
|
116
|
+
progress: 60,
|
|
117
|
+
complete: false,
|
|
118
|
+
});
|
|
119
|
+
try {
|
|
120
|
+
// Check if git is available
|
|
121
|
+
await execAsync('which git');
|
|
122
|
+
await execAsync('git init', { cwd: projectPath });
|
|
123
|
+
await execAsync('git add .', { cwd: projectPath });
|
|
124
|
+
await execAsync('git commit -m "Initial commit from Companion"', { cwd: projectPath });
|
|
125
|
+
// Step 3b: Create GitHub repo if requested
|
|
126
|
+
if (config.options.createGitHubRepo) {
|
|
127
|
+
onProgress?.({
|
|
128
|
+
step: 'Creating GitHub repository',
|
|
129
|
+
progress: 65,
|
|
130
|
+
complete: false,
|
|
131
|
+
});
|
|
132
|
+
try {
|
|
133
|
+
// Check if gh CLI is available
|
|
134
|
+
await execAsync('which gh');
|
|
135
|
+
const visibility = config.options.privateRepo ? '--private' : '--public';
|
|
136
|
+
const repoName = toValidName(config.name);
|
|
137
|
+
await execAsync(`gh repo create ${repoName} ${visibility} --source=. --remote=origin --push`, { cwd: projectPath, timeout: 30000 });
|
|
138
|
+
}
|
|
139
|
+
catch (ghError) {
|
|
140
|
+
console.warn('GitHub repo creation failed (gh CLI may not be installed or authenticated):', ghError);
|
|
141
|
+
// Non-fatal, continue
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch (gitError) {
|
|
146
|
+
console.warn('Git init failed (git may not be installed):', gitError);
|
|
147
|
+
// Non-fatal, continue
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Step 4: Run post-create commands if any
|
|
151
|
+
if (template.postCreate && template.postCreate.length > 0) {
|
|
152
|
+
for (let i = 0; i < template.postCreate.length; i++) {
|
|
153
|
+
const cmd = template.postCreate[i];
|
|
154
|
+
onProgress?.({
|
|
155
|
+
step: cmd.description,
|
|
156
|
+
progress: 70 + Math.floor((i / template.postCreate.length) * 25),
|
|
157
|
+
complete: false,
|
|
158
|
+
});
|
|
159
|
+
try {
|
|
160
|
+
await execAsync(cmd.command, { cwd: projectPath, timeout: 120000 });
|
|
161
|
+
}
|
|
162
|
+
catch (cmdError) {
|
|
163
|
+
console.warn(`Post-create command failed: ${cmd.command}`, cmdError);
|
|
164
|
+
// Non-fatal for MVP, continue
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
onProgress?.({
|
|
169
|
+
step: 'Complete',
|
|
170
|
+
progress: 100,
|
|
171
|
+
complete: true,
|
|
172
|
+
});
|
|
173
|
+
return {
|
|
174
|
+
success: true,
|
|
175
|
+
projectPath,
|
|
176
|
+
filesCreated,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
181
|
+
onProgress?.({
|
|
182
|
+
step: 'Error',
|
|
183
|
+
detail: errorMessage,
|
|
184
|
+
progress: 0,
|
|
185
|
+
complete: true,
|
|
186
|
+
error: errorMessage,
|
|
187
|
+
});
|
|
188
|
+
return {
|
|
189
|
+
success: false,
|
|
190
|
+
projectPath,
|
|
191
|
+
filesCreated,
|
|
192
|
+
error: errorMessage,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Preview what will be created without actually creating
|
|
197
|
+
async function previewScaffold(config) {
|
|
198
|
+
const template = (0, templates_1.getTemplate)(config.stackId);
|
|
199
|
+
if (!template) {
|
|
200
|
+
return { error: `Unknown template: ${config.stackId}` };
|
|
201
|
+
}
|
|
202
|
+
const projectPath = path.join(expandPath(config.location), toValidName(config.name));
|
|
203
|
+
const files = template.files.map(f => f.path);
|
|
204
|
+
return { files, projectPath };
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/scaffold/generator.ts"],"names":[],"mappings":"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"}
|