yap2app 1.1.4 → 1.1.5
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/bin/cli.bundle.js +428 -476
- package/bin/cli.js +428 -476
- package/bridge.js +103 -7
- package/package.json +1 -1
package/bridge.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import http from 'http';
|
|
2
|
+
import https from 'https';
|
|
2
3
|
import fsSync from 'fs';
|
|
3
4
|
import path from 'path';
|
|
4
5
|
import util from 'util';
|
|
@@ -14,6 +15,46 @@ const fs = fsSync.promises || {
|
|
|
14
15
|
|
|
15
16
|
const PORT = Number(process.env.YAP2APP_PORT) || 10420;
|
|
16
17
|
const PROJECT_ROOT = process.cwd();
|
|
18
|
+
const CLOUD_RELAY_URL = process.env.YAP2APP_CLOUD_URL || 'https://yap2app-dot-cybage-hackathon.uc.r.appspot.com';
|
|
19
|
+
const PAIR_CODE = (process.env.YAP2APP_PAIR_CODE || ('CYB-' + Math.floor(100 + Math.random() * 900))).toUpperCase();
|
|
20
|
+
|
|
21
|
+
// Helper to send outbound HTTPS requests to the Yap2App Cloud Relay
|
|
22
|
+
function sendCloudRelayRequest(method, endpoint, payload) {
|
|
23
|
+
return new Promise((resolve) => {
|
|
24
|
+
try {
|
|
25
|
+
const url = new URL(`${CLOUD_RELAY_URL}${endpoint}`);
|
|
26
|
+
const body = payload ? JSON.stringify(payload) : '';
|
|
27
|
+
const req = https.request({
|
|
28
|
+
hostname: url.hostname,
|
|
29
|
+
port: 443,
|
|
30
|
+
path: url.pathname + url.search,
|
|
31
|
+
method: method,
|
|
32
|
+
headers: {
|
|
33
|
+
'Content-Type': 'application/json',
|
|
34
|
+
'Content-Length': Buffer.byteLength(body),
|
|
35
|
+
'User-Agent': 'yap2app-cli/1.1.5'
|
|
36
|
+
},
|
|
37
|
+
timeout: 6000
|
|
38
|
+
}, (res) => {
|
|
39
|
+
let respData = '';
|
|
40
|
+
res.on('data', chunk => respData += chunk);
|
|
41
|
+
res.on('end', () => {
|
|
42
|
+
try {
|
|
43
|
+
resolve({ ok: res.statusCode >= 200 && res.statusCode < 300, status: res.statusCode, data: JSON.parse(respData || '{}') });
|
|
44
|
+
} catch {
|
|
45
|
+
resolve({ ok: false, status: res.statusCode, data: null });
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
req.on('error', () => resolve({ ok: false, status: 0, data: null }));
|
|
50
|
+
req.on('timeout', () => { req.destroy(); resolve({ ok: false, status: 0, data: null }); });
|
|
51
|
+
if (body) req.write(body);
|
|
52
|
+
req.end();
|
|
53
|
+
} catch {
|
|
54
|
+
resolve({ ok: false, status: 0, data: null });
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
17
58
|
|
|
18
59
|
// Bulletproof W3C Private Network Access (PNA) and Dynamic Origin CORS Headers
|
|
19
60
|
function getCorsHeaders(req) {
|
|
@@ -108,8 +149,9 @@ const server = http.createServer(async (req, res) => {
|
|
|
108
149
|
res.end(JSON.stringify({
|
|
109
150
|
status: 'healthy',
|
|
110
151
|
service: 'Yap2App-Localhost-Bridge',
|
|
111
|
-
version: '1.1.
|
|
152
|
+
version: '1.1.5',
|
|
112
153
|
port: PORT,
|
|
154
|
+
pair_code: PAIR_CODE,
|
|
113
155
|
project_root: PROJECT_ROOT,
|
|
114
156
|
project_name: path.basename(PROJECT_ROOT),
|
|
115
157
|
ready: true
|
|
@@ -225,25 +267,78 @@ const server = http.createServer(async (req, res) => {
|
|
|
225
267
|
server.on('error', (err) => {
|
|
226
268
|
if (err && err.code === 'EADDRINUSE') {
|
|
227
269
|
console.log(`\n===============================================================`);
|
|
228
|
-
console.log(`📡
|
|
270
|
+
console.log(`📡 Localhost port ${PORT} is active. Cloud Relay continues seamlessly!`);
|
|
229
271
|
console.log(`📁 Active Workspace: ${PROJECT_ROOT}`);
|
|
230
|
-
console.log(
|
|
272
|
+
console.log(`🔑 Pairing Code: ${PAIR_CODE}`);
|
|
273
|
+
console.log(`🌐 Web Studio: ${CLOUD_RELAY_URL}`);
|
|
231
274
|
console.log(`===============================================================\n`);
|
|
232
275
|
return;
|
|
233
276
|
}
|
|
234
277
|
console.error('[Yap2App Bridge Error]:', err);
|
|
235
278
|
});
|
|
236
279
|
|
|
237
|
-
export function startBridge(port = PORT) {
|
|
280
|
+
export async function startBridge(port = PORT) {
|
|
238
281
|
server.listen(port, '0.0.0.0', () => {
|
|
239
282
|
console.log(`\n===============================================================`);
|
|
240
|
-
console.log(`🚀 Yap2App Localhost Bridge &
|
|
241
|
-
console.log(`📡
|
|
283
|
+
console.log(`🚀 Yap2App Localhost Bridge & Telemetry is ACTIVE!`);
|
|
284
|
+
console.log(`📡 Local Endpoint: http://127.0.0.1:${port}`);
|
|
242
285
|
console.log(`📁 Active Workspace: ${PROJECT_ROOT}`);
|
|
243
|
-
console.log(
|
|
286
|
+
console.log(`🔑 Pairing Code: ${PAIR_CODE}`);
|
|
287
|
+
console.log(`🌐 Connected to Web Studio: ${CLOUD_RELAY_URL}`);
|
|
288
|
+
console.log(`🛡️ Enterprise Diff, W3C PNA & Cloud Relay Enabled`);
|
|
244
289
|
console.log(`===============================================================\n`);
|
|
245
290
|
console.log(`Ready for 1-click sync from Yap2App Web Studio UI...\n`);
|
|
246
291
|
});
|
|
292
|
+
|
|
293
|
+
// Initial scan and Cloud Relay registration
|
|
294
|
+
try {
|
|
295
|
+
const initialContext = await scanCodebase(PROJECT_ROOT);
|
|
296
|
+
await sendCloudRelayRequest('POST', '/api/v1/bridge/heartbeat', {
|
|
297
|
+
pair_code: PAIR_CODE,
|
|
298
|
+
project_name: path.basename(PROJECT_ROOT),
|
|
299
|
+
project_root: PROJECT_ROOT,
|
|
300
|
+
framework: initialContext.framework,
|
|
301
|
+
context: initialContext,
|
|
302
|
+
version: '1.1.5'
|
|
303
|
+
});
|
|
304
|
+
} catch (e) {}
|
|
305
|
+
|
|
306
|
+
// Periodic Cloud Relay heartbeat & write execution loop (every 3.5 seconds)
|
|
307
|
+
setInterval(async () => {
|
|
308
|
+
try {
|
|
309
|
+
const context = await scanCodebase(PROJECT_ROOT);
|
|
310
|
+
const hbResult = await sendCloudRelayRequest('POST', '/api/v1/bridge/heartbeat', {
|
|
311
|
+
pair_code: PAIR_CODE,
|
|
312
|
+
project_name: path.basename(PROJECT_ROOT),
|
|
313
|
+
project_root: PROJECT_ROOT,
|
|
314
|
+
framework: context.framework,
|
|
315
|
+
context: context,
|
|
316
|
+
version: '1.1.5'
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// If pending write tasks, fetch and execute them on local disk
|
|
320
|
+
if (hbResult && hbResult.data && hbResult.data.pending_writes_count > 0) {
|
|
321
|
+
const pollResult = await sendCloudRelayRequest('GET', `/api/v1/bridge/poll-writes?pair_code=${PAIR_CODE}`);
|
|
322
|
+
const tasks = (pollResult.data && pollResult.data.pending_tasks) || [];
|
|
323
|
+
for (const task of tasks) {
|
|
324
|
+
const written = [];
|
|
325
|
+
for (const file of (task.files || [])) {
|
|
326
|
+
const fullPath = path.join(PROJECT_ROOT, file.path);
|
|
327
|
+
await fs.mkdir(path.dirname(fullPath), { recursive: true });
|
|
328
|
+
await fs.writeFile(fullPath, file.content, 'utf8');
|
|
329
|
+
console.log(`[Yap2App Bridge] ✍️ Wrote approved file: ${file.path}`);
|
|
330
|
+
written.push(file.path);
|
|
331
|
+
}
|
|
332
|
+
await sendCloudRelayRequest('POST', '/api/v1/bridge/complete-write', {
|
|
333
|
+
task_id: task.task_id,
|
|
334
|
+
success: true,
|
|
335
|
+
written,
|
|
336
|
+
message: `Wrote ${written.length} file(s) directly to ${path.basename(PROJECT_ROOT)}`
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
} catch {}
|
|
341
|
+
}, 3500);
|
|
247
342
|
}
|
|
248
343
|
|
|
249
344
|
// Direct execution
|
|
@@ -252,3 +347,4 @@ if (isDirectRun) {
|
|
|
252
347
|
startBridge();
|
|
253
348
|
}
|
|
254
349
|
|
|
350
|
+
|