yap2app 1.2.0 → 1.2.2
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 +89 -7
- package/bin/cli.js +89 -7
- package/bridge.js +104 -6
- package/package.json +2 -1
package/bin/cli.bundle.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
import { createRequire } from 'module'; const require = createRequire(import.meta.url);
|
|
3
2
|
var __create = Object.create;
|
|
4
3
|
var __defProp = Object.defineProperty;
|
|
@@ -7029,6 +7028,7 @@ import http from "http";
|
|
|
7029
7028
|
import fsSync2 from "fs";
|
|
7030
7029
|
import path2 from "path";
|
|
7031
7030
|
import util2 from "util";
|
|
7031
|
+
import { execSync } from "child_process";
|
|
7032
7032
|
|
|
7033
7033
|
// scanner.js
|
|
7034
7034
|
import fsSync from "fs";
|
|
@@ -7580,7 +7580,23 @@ var fs2 = fsSync2.promises || {
|
|
|
7580
7580
|
var PORT = Number(process.env.YAP2APP_PORT) || 10420;
|
|
7581
7581
|
var PROJECT_ROOT = process.cwd();
|
|
7582
7582
|
var PAIR_CODE = (process.env.YAP2APP_PAIR_CODE || "Y2A-" + Math.floor(1e3 + Math.random() * 9e3)).toUpperCase();
|
|
7583
|
-
var CLI_VERSION = "1.2.
|
|
7583
|
+
var CLI_VERSION = "1.2.2";
|
|
7584
|
+
function getGitUserEmail() {
|
|
7585
|
+
try {
|
|
7586
|
+
const email2 = execSync("git config user.email", { encoding: "utf8", stdio: ["pipe", "pipe", "ignore"] }).trim();
|
|
7587
|
+
return email2 || null;
|
|
7588
|
+
} catch (e) {
|
|
7589
|
+
return null;
|
|
7590
|
+
}
|
|
7591
|
+
}
|
|
7592
|
+
function resolveUserEmail() {
|
|
7593
|
+
const emailArgIdx = process.argv.indexOf("--email");
|
|
7594
|
+
if (emailArgIdx !== -1 && process.argv[emailArgIdx + 1]) {
|
|
7595
|
+
return process.argv[emailArgIdx + 1].trim();
|
|
7596
|
+
}
|
|
7597
|
+
return (process.env.YAP2APP_EMAIL || getGitUserEmail() || "").trim();
|
|
7598
|
+
}
|
|
7599
|
+
var USER_EMAIL = resolveUserEmail();
|
|
7584
7600
|
function safeResolvePath(baseDir, relativePath) {
|
|
7585
7601
|
const cleanRel = (relativePath || "").replace(/^[\\\/]+/, "");
|
|
7586
7602
|
const resolved = path2.resolve(baseDir, cleanRel);
|
|
@@ -7755,36 +7771,100 @@ var server = http.createServer(async (req, res) => {
|
|
|
7755
7771
|
res.writeHead(404, headers);
|
|
7756
7772
|
res.end(JSON.stringify({ error: "Endpoint Not Found", path: pathname }));
|
|
7757
7773
|
});
|
|
7774
|
+
var CLOUD_URL = process.env.YAP2APP_CLOUD_URL || "https://yap2app-dot-cybage-hackathon.uc.r.appspot.com";
|
|
7775
|
+
async function sendCloudHeartbeat() {
|
|
7776
|
+
try {
|
|
7777
|
+
const context = await scanCodebase(PROJECT_ROOT);
|
|
7778
|
+
const payload = {
|
|
7779
|
+
pair_code: PAIR_CODE,
|
|
7780
|
+
user_email: USER_EMAIL || void 0,
|
|
7781
|
+
project_name: path2.basename(PROJECT_ROOT),
|
|
7782
|
+
project_root: PROJECT_ROOT,
|
|
7783
|
+
framework: context.framework || "plain_html_css_js",
|
|
7784
|
+
context,
|
|
7785
|
+
version: CLI_VERSION
|
|
7786
|
+
};
|
|
7787
|
+
const res = await fetch(`${CLOUD_URL}/api/v1/bridge/heartbeat`, {
|
|
7788
|
+
method: "POST",
|
|
7789
|
+
headers: { "Content-Type": "application/json" },
|
|
7790
|
+
body: JSON.stringify(payload)
|
|
7791
|
+
});
|
|
7792
|
+
if (res.ok) {
|
|
7793
|
+
const data = await res.json();
|
|
7794
|
+
if (data.pending_writes_count > 0) {
|
|
7795
|
+
await pollAndExecuteCloudWrites();
|
|
7796
|
+
}
|
|
7797
|
+
}
|
|
7798
|
+
} catch (err) {
|
|
7799
|
+
}
|
|
7800
|
+
}
|
|
7801
|
+
async function pollAndExecuteCloudWrites() {
|
|
7802
|
+
try {
|
|
7803
|
+
const res = await fetch(`${CLOUD_URL}/api/v1/bridge/poll-writes?pair_code=${encodeURIComponent(PAIR_CODE)}`);
|
|
7804
|
+
if (!res.ok) return;
|
|
7805
|
+
const data = await res.json();
|
|
7806
|
+
const tasks = data.pending_tasks || [];
|
|
7807
|
+
for (const task of tasks) {
|
|
7808
|
+
const written = [];
|
|
7809
|
+
for (const file of task.files || []) {
|
|
7810
|
+
const fullPath = safeResolvePath(PROJECT_ROOT, file.path);
|
|
7811
|
+
await fs2.mkdir(path2.dirname(fullPath), { recursive: true });
|
|
7812
|
+
await fs2.writeFile(fullPath, file.content, "utf8");
|
|
7813
|
+
console.log(` [bridge] Wrote ${file.path}`);
|
|
7814
|
+
written.push(file.path);
|
|
7815
|
+
}
|
|
7816
|
+
await fetch(`${CLOUD_URL}/api/v1/bridge/complete-write`, {
|
|
7817
|
+
method: "POST",
|
|
7818
|
+
headers: { "Content-Type": "application/json" },
|
|
7819
|
+
body: JSON.stringify({
|
|
7820
|
+
task_id: task.task_id,
|
|
7821
|
+
success: true,
|
|
7822
|
+
written,
|
|
7823
|
+
message: `Successfully wrote ${written.length} files to ${path2.basename(PROJECT_ROOT)}`
|
|
7824
|
+
})
|
|
7825
|
+
});
|
|
7826
|
+
}
|
|
7827
|
+
} catch (err) {
|
|
7828
|
+
console.error(" [bridge] Cloud write sync error:", err.message);
|
|
7829
|
+
}
|
|
7830
|
+
}
|
|
7758
7831
|
server.on("error", (err) => {
|
|
7759
7832
|
if (err && err.code === "EADDRINUSE") {
|
|
7760
7833
|
console.log(`
|
|
7761
7834
|
---------------------------------------------------------------`);
|
|
7762
7835
|
console.log(`Yap2App Local Bridge v${CLI_VERSION}`);
|
|
7836
|
+
console.log(`Pair Code: ${PAIR_CODE}`);
|
|
7837
|
+
if (USER_EMAIL) console.log(`Linked Email: ${USER_EMAIL}`);
|
|
7763
7838
|
console.log(`Local Endpoint: http://127.0.0.1:${PORT}`);
|
|
7764
7839
|
console.log(`Active Workspace: ${PROJECT_ROOT}`);
|
|
7840
|
+
console.log(`Web Studio Link: https://yap2app-dot-cybage-hackathon.uc.r.appspot.com/?pair=${PAIR_CODE}`);
|
|
7765
7841
|
console.log(`Status: Already active & ready on port ${PORT}`);
|
|
7766
7842
|
console.log(`---------------------------------------------------------------
|
|
7767
7843
|
`);
|
|
7768
|
-
console.log(`Bridge is running.`);
|
|
7844
|
+
console.log(`Bridge is running & synced.`);
|
|
7769
7845
|
console.log(`Open Web Studio in your browser to sync components to this workspace.`);
|
|
7770
7846
|
console.log(`Press Ctrl/Cmd+C to stop.
|
|
7771
7847
|
`);
|
|
7848
|
+
sendCloudHeartbeat();
|
|
7849
|
+
setInterval(sendCloudHeartbeat, 3e3);
|
|
7772
7850
|
return;
|
|
7773
7851
|
}
|
|
7774
7852
|
console.error(" [bridge] Error:", err.message || err);
|
|
7775
7853
|
});
|
|
7776
7854
|
async function startBridge(port = PORT) {
|
|
7777
|
-
server.listen(port,
|
|
7855
|
+
server.listen(port, () => {
|
|
7778
7856
|
console.log(`
|
|
7779
7857
|
---------------------------------------------------------------`);
|
|
7780
7858
|
console.log(`Yap2App Local Bridge v${CLI_VERSION}`);
|
|
7859
|
+
console.log(`Pair Code: ${PAIR_CODE}`);
|
|
7860
|
+
if (USER_EMAIL) console.log(`Linked Email: ${USER_EMAIL}`);
|
|
7781
7861
|
console.log(`Local Endpoint: http://127.0.0.1:${port}`);
|
|
7782
7862
|
console.log(`Active Workspace: ${PROJECT_ROOT}`);
|
|
7783
|
-
console.log(`Web Studio:
|
|
7863
|
+
console.log(`Web Studio Link: https://yap2app-dot-cybage-hackathon.uc.r.appspot.com/?pair=${PAIR_CODE}`);
|
|
7784
7864
|
console.log(`---------------------------------------------------------------
|
|
7785
7865
|
`);
|
|
7786
|
-
console.log(`Bridge is running.`);
|
|
7787
|
-
console.log(`Open Web Studio in your browser
|
|
7866
|
+
console.log(`Bridge is running & synced.`);
|
|
7867
|
+
console.log(`Open Web Studio in your browser or click the link above to connect.`);
|
|
7788
7868
|
console.log(`Press Ctrl/Cmd+C to stop.
|
|
7789
7869
|
`);
|
|
7790
7870
|
});
|
|
@@ -7797,6 +7877,8 @@ async function startBridge(port = PORT) {
|
|
|
7797
7877
|
}
|
|
7798
7878
|
} catch (e) {
|
|
7799
7879
|
}
|
|
7880
|
+
sendCloudHeartbeat();
|
|
7881
|
+
setInterval(sendCloudHeartbeat, 3e3);
|
|
7800
7882
|
}
|
|
7801
7883
|
var isDirectRun = Boolean(typeof process !== "undefined" && process.argv && process.argv[1] && (process.argv[1].endsWith("bridge.js") || process.argv[1].endsWith("bridge")));
|
|
7802
7884
|
if (isDirectRun) {
|
package/bin/cli.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
import { createRequire } from 'module'; const require = createRequire(import.meta.url);
|
|
3
2
|
var __create = Object.create;
|
|
4
3
|
var __defProp = Object.defineProperty;
|
|
@@ -7029,6 +7028,7 @@ import http from "http";
|
|
|
7029
7028
|
import fsSync2 from "fs";
|
|
7030
7029
|
import path2 from "path";
|
|
7031
7030
|
import util2 from "util";
|
|
7031
|
+
import { execSync } from "child_process";
|
|
7032
7032
|
|
|
7033
7033
|
// scanner.js
|
|
7034
7034
|
import fsSync from "fs";
|
|
@@ -7580,7 +7580,23 @@ var fs2 = fsSync2.promises || {
|
|
|
7580
7580
|
var PORT = Number(process.env.YAP2APP_PORT) || 10420;
|
|
7581
7581
|
var PROJECT_ROOT = process.cwd();
|
|
7582
7582
|
var PAIR_CODE = (process.env.YAP2APP_PAIR_CODE || "Y2A-" + Math.floor(1e3 + Math.random() * 9e3)).toUpperCase();
|
|
7583
|
-
var CLI_VERSION = "1.2.
|
|
7583
|
+
var CLI_VERSION = "1.2.2";
|
|
7584
|
+
function getGitUserEmail() {
|
|
7585
|
+
try {
|
|
7586
|
+
const email2 = execSync("git config user.email", { encoding: "utf8", stdio: ["pipe", "pipe", "ignore"] }).trim();
|
|
7587
|
+
return email2 || null;
|
|
7588
|
+
} catch (e) {
|
|
7589
|
+
return null;
|
|
7590
|
+
}
|
|
7591
|
+
}
|
|
7592
|
+
function resolveUserEmail() {
|
|
7593
|
+
const emailArgIdx = process.argv.indexOf("--email");
|
|
7594
|
+
if (emailArgIdx !== -1 && process.argv[emailArgIdx + 1]) {
|
|
7595
|
+
return process.argv[emailArgIdx + 1].trim();
|
|
7596
|
+
}
|
|
7597
|
+
return (process.env.YAP2APP_EMAIL || getGitUserEmail() || "").trim();
|
|
7598
|
+
}
|
|
7599
|
+
var USER_EMAIL = resolveUserEmail();
|
|
7584
7600
|
function safeResolvePath(baseDir, relativePath) {
|
|
7585
7601
|
const cleanRel = (relativePath || "").replace(/^[\\\/]+/, "");
|
|
7586
7602
|
const resolved = path2.resolve(baseDir, cleanRel);
|
|
@@ -7755,36 +7771,100 @@ var server = http.createServer(async (req, res) => {
|
|
|
7755
7771
|
res.writeHead(404, headers);
|
|
7756
7772
|
res.end(JSON.stringify({ error: "Endpoint Not Found", path: pathname }));
|
|
7757
7773
|
});
|
|
7774
|
+
var CLOUD_URL = process.env.YAP2APP_CLOUD_URL || "https://yap2app-dot-cybage-hackathon.uc.r.appspot.com";
|
|
7775
|
+
async function sendCloudHeartbeat() {
|
|
7776
|
+
try {
|
|
7777
|
+
const context = await scanCodebase(PROJECT_ROOT);
|
|
7778
|
+
const payload = {
|
|
7779
|
+
pair_code: PAIR_CODE,
|
|
7780
|
+
user_email: USER_EMAIL || void 0,
|
|
7781
|
+
project_name: path2.basename(PROJECT_ROOT),
|
|
7782
|
+
project_root: PROJECT_ROOT,
|
|
7783
|
+
framework: context.framework || "plain_html_css_js",
|
|
7784
|
+
context,
|
|
7785
|
+
version: CLI_VERSION
|
|
7786
|
+
};
|
|
7787
|
+
const res = await fetch(`${CLOUD_URL}/api/v1/bridge/heartbeat`, {
|
|
7788
|
+
method: "POST",
|
|
7789
|
+
headers: { "Content-Type": "application/json" },
|
|
7790
|
+
body: JSON.stringify(payload)
|
|
7791
|
+
});
|
|
7792
|
+
if (res.ok) {
|
|
7793
|
+
const data = await res.json();
|
|
7794
|
+
if (data.pending_writes_count > 0) {
|
|
7795
|
+
await pollAndExecuteCloudWrites();
|
|
7796
|
+
}
|
|
7797
|
+
}
|
|
7798
|
+
} catch (err) {
|
|
7799
|
+
}
|
|
7800
|
+
}
|
|
7801
|
+
async function pollAndExecuteCloudWrites() {
|
|
7802
|
+
try {
|
|
7803
|
+
const res = await fetch(`${CLOUD_URL}/api/v1/bridge/poll-writes?pair_code=${encodeURIComponent(PAIR_CODE)}`);
|
|
7804
|
+
if (!res.ok) return;
|
|
7805
|
+
const data = await res.json();
|
|
7806
|
+
const tasks = data.pending_tasks || [];
|
|
7807
|
+
for (const task of tasks) {
|
|
7808
|
+
const written = [];
|
|
7809
|
+
for (const file of task.files || []) {
|
|
7810
|
+
const fullPath = safeResolvePath(PROJECT_ROOT, file.path);
|
|
7811
|
+
await fs2.mkdir(path2.dirname(fullPath), { recursive: true });
|
|
7812
|
+
await fs2.writeFile(fullPath, file.content, "utf8");
|
|
7813
|
+
console.log(` [bridge] Wrote ${file.path}`);
|
|
7814
|
+
written.push(file.path);
|
|
7815
|
+
}
|
|
7816
|
+
await fetch(`${CLOUD_URL}/api/v1/bridge/complete-write`, {
|
|
7817
|
+
method: "POST",
|
|
7818
|
+
headers: { "Content-Type": "application/json" },
|
|
7819
|
+
body: JSON.stringify({
|
|
7820
|
+
task_id: task.task_id,
|
|
7821
|
+
success: true,
|
|
7822
|
+
written,
|
|
7823
|
+
message: `Successfully wrote ${written.length} files to ${path2.basename(PROJECT_ROOT)}`
|
|
7824
|
+
})
|
|
7825
|
+
});
|
|
7826
|
+
}
|
|
7827
|
+
} catch (err) {
|
|
7828
|
+
console.error(" [bridge] Cloud write sync error:", err.message);
|
|
7829
|
+
}
|
|
7830
|
+
}
|
|
7758
7831
|
server.on("error", (err) => {
|
|
7759
7832
|
if (err && err.code === "EADDRINUSE") {
|
|
7760
7833
|
console.log(`
|
|
7761
7834
|
---------------------------------------------------------------`);
|
|
7762
7835
|
console.log(`Yap2App Local Bridge v${CLI_VERSION}`);
|
|
7836
|
+
console.log(`Pair Code: ${PAIR_CODE}`);
|
|
7837
|
+
if (USER_EMAIL) console.log(`Linked Email: ${USER_EMAIL}`);
|
|
7763
7838
|
console.log(`Local Endpoint: http://127.0.0.1:${PORT}`);
|
|
7764
7839
|
console.log(`Active Workspace: ${PROJECT_ROOT}`);
|
|
7840
|
+
console.log(`Web Studio Link: https://yap2app-dot-cybage-hackathon.uc.r.appspot.com/?pair=${PAIR_CODE}`);
|
|
7765
7841
|
console.log(`Status: Already active & ready on port ${PORT}`);
|
|
7766
7842
|
console.log(`---------------------------------------------------------------
|
|
7767
7843
|
`);
|
|
7768
|
-
console.log(`Bridge is running.`);
|
|
7844
|
+
console.log(`Bridge is running & synced.`);
|
|
7769
7845
|
console.log(`Open Web Studio in your browser to sync components to this workspace.`);
|
|
7770
7846
|
console.log(`Press Ctrl/Cmd+C to stop.
|
|
7771
7847
|
`);
|
|
7848
|
+
sendCloudHeartbeat();
|
|
7849
|
+
setInterval(sendCloudHeartbeat, 3e3);
|
|
7772
7850
|
return;
|
|
7773
7851
|
}
|
|
7774
7852
|
console.error(" [bridge] Error:", err.message || err);
|
|
7775
7853
|
});
|
|
7776
7854
|
async function startBridge(port = PORT) {
|
|
7777
|
-
server.listen(port,
|
|
7855
|
+
server.listen(port, () => {
|
|
7778
7856
|
console.log(`
|
|
7779
7857
|
---------------------------------------------------------------`);
|
|
7780
7858
|
console.log(`Yap2App Local Bridge v${CLI_VERSION}`);
|
|
7859
|
+
console.log(`Pair Code: ${PAIR_CODE}`);
|
|
7860
|
+
if (USER_EMAIL) console.log(`Linked Email: ${USER_EMAIL}`);
|
|
7781
7861
|
console.log(`Local Endpoint: http://127.0.0.1:${port}`);
|
|
7782
7862
|
console.log(`Active Workspace: ${PROJECT_ROOT}`);
|
|
7783
|
-
console.log(`Web Studio:
|
|
7863
|
+
console.log(`Web Studio Link: https://yap2app-dot-cybage-hackathon.uc.r.appspot.com/?pair=${PAIR_CODE}`);
|
|
7784
7864
|
console.log(`---------------------------------------------------------------
|
|
7785
7865
|
`);
|
|
7786
|
-
console.log(`Bridge is running.`);
|
|
7787
|
-
console.log(`Open Web Studio in your browser
|
|
7866
|
+
console.log(`Bridge is running & synced.`);
|
|
7867
|
+
console.log(`Open Web Studio in your browser or click the link above to connect.`);
|
|
7788
7868
|
console.log(`Press Ctrl/Cmd+C to stop.
|
|
7789
7869
|
`);
|
|
7790
7870
|
});
|
|
@@ -7797,6 +7877,8 @@ async function startBridge(port = PORT) {
|
|
|
7797
7877
|
}
|
|
7798
7878
|
} catch (e) {
|
|
7799
7879
|
}
|
|
7880
|
+
sendCloudHeartbeat();
|
|
7881
|
+
setInterval(sendCloudHeartbeat, 3e3);
|
|
7800
7882
|
}
|
|
7801
7883
|
var isDirectRun = Boolean(typeof process !== "undefined" && process.argv && process.argv[1] && (process.argv[1].endsWith("bridge.js") || process.argv[1].endsWith("bridge")));
|
|
7802
7884
|
if (isDirectRun) {
|
package/bridge.js
CHANGED
|
@@ -2,6 +2,7 @@ import http from 'http';
|
|
|
2
2
|
import fsSync from 'fs';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import util from 'util';
|
|
5
|
+
import { execSync } from 'child_process';
|
|
5
6
|
import { scanCodebase } from './scanner.js';
|
|
6
7
|
|
|
7
8
|
const fs = fsSync.promises || {
|
|
@@ -15,7 +16,26 @@ const fs = fsSync.promises || {
|
|
|
15
16
|
const PORT = Number(process.env.YAP2APP_PORT) || 10420;
|
|
16
17
|
const PROJECT_ROOT = process.cwd();
|
|
17
18
|
const PAIR_CODE = (process.env.YAP2APP_PAIR_CODE || ('Y2A-' + Math.floor(1000 + Math.random() * 9000))).toUpperCase();
|
|
18
|
-
const CLI_VERSION = '1.2.
|
|
19
|
+
const CLI_VERSION = '1.2.2';
|
|
20
|
+
|
|
21
|
+
function getGitUserEmail() {
|
|
22
|
+
try {
|
|
23
|
+
const email = execSync('git config user.email', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
|
|
24
|
+
return email || null;
|
|
25
|
+
} catch (e) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function resolveUserEmail() {
|
|
31
|
+
const emailArgIdx = process.argv.indexOf('--email');
|
|
32
|
+
if (emailArgIdx !== -1 && process.argv[emailArgIdx + 1]) {
|
|
33
|
+
return process.argv[emailArgIdx + 1].trim();
|
|
34
|
+
}
|
|
35
|
+
return (process.env.YAP2APP_EMAIL || getGitUserEmail() || '').trim();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const USER_EMAIL = resolveUserEmail();
|
|
19
39
|
|
|
20
40
|
/**
|
|
21
41
|
* Validates and resolves relative file paths strictly inside PROJECT_ROOT.
|
|
@@ -237,33 +257,107 @@ const server = http.createServer(async (req, res) => {
|
|
|
237
257
|
res.end(JSON.stringify({ error: 'Endpoint Not Found', path: pathname }));
|
|
238
258
|
});
|
|
239
259
|
|
|
260
|
+
const CLOUD_URL = process.env.YAP2APP_CLOUD_URL || 'https://yap2app-dot-cybage-hackathon.uc.r.appspot.com';
|
|
261
|
+
|
|
262
|
+
async function sendCloudHeartbeat() {
|
|
263
|
+
try {
|
|
264
|
+
const context = await scanCodebase(PROJECT_ROOT);
|
|
265
|
+
const payload = {
|
|
266
|
+
pair_code: PAIR_CODE,
|
|
267
|
+
user_email: USER_EMAIL || undefined,
|
|
268
|
+
project_name: path.basename(PROJECT_ROOT),
|
|
269
|
+
project_root: PROJECT_ROOT,
|
|
270
|
+
framework: context.framework || 'plain_html_css_js',
|
|
271
|
+
context: context,
|
|
272
|
+
version: CLI_VERSION
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
const res = await fetch(`${CLOUD_URL}/api/v1/bridge/heartbeat`, {
|
|
276
|
+
method: 'POST',
|
|
277
|
+
headers: { 'Content-Type': 'application/json' },
|
|
278
|
+
body: JSON.stringify(payload)
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
if (res.ok) {
|
|
282
|
+
const data = await res.json();
|
|
283
|
+
if (data.pending_writes_count > 0) {
|
|
284
|
+
await pollAndExecuteCloudWrites();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
} catch (err) {
|
|
288
|
+
// Quiet fallback if offline or unreachable
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
async function pollAndExecuteCloudWrites() {
|
|
293
|
+
try {
|
|
294
|
+
const res = await fetch(`${CLOUD_URL}/api/v1/bridge/poll-writes?pair_code=${encodeURIComponent(PAIR_CODE)}`);
|
|
295
|
+
if (!res.ok) return;
|
|
296
|
+
const data = await res.json();
|
|
297
|
+
const tasks = data.pending_tasks || [];
|
|
298
|
+
|
|
299
|
+
for (const task of tasks) {
|
|
300
|
+
const written = [];
|
|
301
|
+
for (const file of task.files || []) {
|
|
302
|
+
const fullPath = safeResolvePath(PROJECT_ROOT, file.path);
|
|
303
|
+
await fs.mkdir(path.dirname(fullPath), { recursive: true });
|
|
304
|
+
await fs.writeFile(fullPath, file.content, 'utf8');
|
|
305
|
+
console.log(` [bridge] Wrote ${file.path}`);
|
|
306
|
+
written.push(file.path);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
await fetch(`${CLOUD_URL}/api/v1/bridge/complete-write`, {
|
|
310
|
+
method: 'POST',
|
|
311
|
+
headers: { 'Content-Type': 'application/json' },
|
|
312
|
+
body: JSON.stringify({
|
|
313
|
+
task_id: task.task_id,
|
|
314
|
+
success: true,
|
|
315
|
+
written,
|
|
316
|
+
message: `Successfully wrote ${written.length} files to ${path.basename(PROJECT_ROOT)}`
|
|
317
|
+
})
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
} catch (err) {
|
|
321
|
+
console.error(' [bridge] Cloud write sync error:', err.message);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
240
325
|
// Gracefully handle EADDRINUSE without crashing
|
|
241
326
|
server.on('error', (err) => {
|
|
242
327
|
if (err && err.code === 'EADDRINUSE') {
|
|
243
328
|
console.log(`\n---------------------------------------------------------------`);
|
|
244
329
|
console.log(`Yap2App Local Bridge v${CLI_VERSION}`);
|
|
330
|
+
console.log(`Pair Code: ${PAIR_CODE}`);
|
|
331
|
+
if (USER_EMAIL) console.log(`Linked Email: ${USER_EMAIL}`);
|
|
245
332
|
console.log(`Local Endpoint: http://127.0.0.1:${PORT}`);
|
|
246
333
|
console.log(`Active Workspace: ${PROJECT_ROOT}`);
|
|
334
|
+
console.log(`Web Studio Link: https://yap2app-dot-cybage-hackathon.uc.r.appspot.com/?pair=${PAIR_CODE}`);
|
|
247
335
|
console.log(`Status: Already active & ready on port ${PORT}`);
|
|
248
336
|
console.log(`---------------------------------------------------------------\n`);
|
|
249
|
-
console.log(`Bridge is running.`);
|
|
337
|
+
console.log(`Bridge is running & synced.`);
|
|
250
338
|
console.log(`Open Web Studio in your browser to sync components to this workspace.`);
|
|
251
339
|
console.log(`Press Ctrl/Cmd+C to stop.\n`);
|
|
340
|
+
|
|
341
|
+
// Still maintain cloud heartbeat even if port was bound by another process
|
|
342
|
+
sendCloudHeartbeat();
|
|
343
|
+
setInterval(sendCloudHeartbeat, 3000);
|
|
252
344
|
return;
|
|
253
345
|
}
|
|
254
346
|
console.error(' [bridge] Error:', err.message || err);
|
|
255
347
|
});
|
|
256
348
|
|
|
257
349
|
export async function startBridge(port = PORT) {
|
|
258
|
-
server.listen(port,
|
|
350
|
+
server.listen(port, () => {
|
|
259
351
|
console.log(`\n---------------------------------------------------------------`);
|
|
260
352
|
console.log(`Yap2App Local Bridge v${CLI_VERSION}`);
|
|
353
|
+
console.log(`Pair Code: ${PAIR_CODE}`);
|
|
354
|
+
if (USER_EMAIL) console.log(`Linked Email: ${USER_EMAIL}`);
|
|
261
355
|
console.log(`Local Endpoint: http://127.0.0.1:${port}`);
|
|
262
356
|
console.log(`Active Workspace: ${PROJECT_ROOT}`);
|
|
263
|
-
console.log(`Web Studio:
|
|
357
|
+
console.log(`Web Studio Link: https://yap2app-dot-cybage-hackathon.uc.r.appspot.com/?pair=${PAIR_CODE}`);
|
|
264
358
|
console.log(`---------------------------------------------------------------\n`);
|
|
265
|
-
console.log(`Bridge is running.`);
|
|
266
|
-
console.log(`Open Web Studio in your browser
|
|
359
|
+
console.log(`Bridge is running & synced.`);
|
|
360
|
+
console.log(`Open Web Studio in your browser or click the link above to connect.`);
|
|
267
361
|
console.log(`Press Ctrl/Cmd+C to stop.\n`);
|
|
268
362
|
});
|
|
269
363
|
|
|
@@ -275,6 +369,10 @@ export async function startBridge(port = PORT) {
|
|
|
275
369
|
console.log(` Yap2App will automatically scaffold directories and write files when synced from Web Studio.\n`);
|
|
276
370
|
}
|
|
277
371
|
} catch (e) {}
|
|
372
|
+
|
|
373
|
+
// Start bidirectional cloud relay heartbeat
|
|
374
|
+
sendCloudHeartbeat();
|
|
375
|
+
setInterval(sendCloudHeartbeat, 3000);
|
|
278
376
|
}
|
|
279
377
|
|
|
280
378
|
// Direct execution
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yap2app",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Autonomous Vibe-to-Prod Localhost Bridge & Model Context Protocol (MCP) Server",
|
|
6
6
|
"main": "bin/cli.bundle.js",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"registry": "https://registry.npmjs.org/"
|
|
25
25
|
},
|
|
26
26
|
"scripts": {
|
|
27
|
+
"build": "npx esbuild bin/cli-esm.js --bundle --platform=node --target=node18 --format=esm --banner:js=\"import { createRequire } from 'module'; const require = createRequire(import.meta.url);\" --outfile=bin/cli.bundle.js && cp bin/cli.bundle.js bin/cli.js",
|
|
27
28
|
"start": "node ./bin/cli.js start",
|
|
28
29
|
"bridge": "node ./bin/cli.js bridge",
|
|
29
30
|
"mcp": "node ./bin/cli.js mcp",
|