yap2app 1.1.8 → 1.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.
- package/bin/cli-esm.js +1 -3
- package/bin/cli.bundle.js +11 -96
- package/bin/cli.js +11 -96
- package/bridge.js +9 -96
- package/package.json +1 -1
package/bin/cli-esm.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
1
|
import '../polyfills.js';
|
|
4
2
|
import { startBridge } from '../bridge.js';
|
|
5
3
|
import { runMcpServer } from '../mcp.js';
|
|
@@ -20,7 +18,7 @@ async function main() {
|
|
|
20
18
|
console.log(` Path Alias: ${context.path_alias || '@/'}`);
|
|
21
19
|
console.log(` Files: ${context.discovered_files?.length || 0}`);
|
|
22
20
|
console.log(` Components: ${(context.component_names || []).join(', ') || 'None'}\n`);
|
|
23
|
-
} else if (command === 'init' || command === 'install') {
|
|
21
|
+
} else if (command === 'init' || command === 'install' || command === 'insall') {
|
|
24
22
|
const context = await scanCodebase(process.cwd());
|
|
25
23
|
console.log(`\n⚡ Yap2App Workspace Initializer:`);
|
|
26
24
|
console.log(` Directory: ${context.project_root}`);
|
package/bin/cli.bundle.js
CHANGED
|
@@ -3552,7 +3552,7 @@ var require_schemes = __commonJS({
|
|
|
3552
3552
|
serialize: httpSerialize
|
|
3553
3553
|
}
|
|
3554
3554
|
);
|
|
3555
|
-
var
|
|
3555
|
+
var https = (
|
|
3556
3556
|
/** @type {SchemeHandler} */
|
|
3557
3557
|
{
|
|
3558
3558
|
scheme: "https",
|
|
@@ -3601,7 +3601,7 @@ var require_schemes = __commonJS({
|
|
|
3601
3601
|
/** @type {Record<SchemeName, SchemeHandler>} */
|
|
3602
3602
|
{
|
|
3603
3603
|
http: http2,
|
|
3604
|
-
https
|
|
3604
|
+
https,
|
|
3605
3605
|
ws,
|
|
3606
3606
|
wss,
|
|
3607
3607
|
urn,
|
|
@@ -7026,7 +7026,6 @@ if (!Promise.allSettled) {
|
|
|
7026
7026
|
|
|
7027
7027
|
// bridge.js
|
|
7028
7028
|
import http from "http";
|
|
7029
|
-
import https from "https";
|
|
7030
7029
|
import fsSync2 from "fs";
|
|
7031
7030
|
import path2 from "path";
|
|
7032
7031
|
import util2 from "util";
|
|
@@ -7580,9 +7579,8 @@ var fs2 = fsSync2.promises || {
|
|
|
7580
7579
|
};
|
|
7581
7580
|
var PORT = Number(process.env.YAP2APP_PORT) || 10420;
|
|
7582
7581
|
var PROJECT_ROOT = process.cwd();
|
|
7583
|
-
var
|
|
7584
|
-
var
|
|
7585
|
-
var CLI_VERSION = "1.1.8";
|
|
7582
|
+
var PAIR_CODE = (process.env.YAP2APP_PAIR_CODE || "Y2A-" + Math.floor(1e3 + Math.random() * 9e3)).toUpperCase();
|
|
7583
|
+
var CLI_VERSION = "1.2.0";
|
|
7586
7584
|
function safeResolvePath(baseDir, relativePath) {
|
|
7587
7585
|
const cleanRel = (relativePath || "").replace(/^[\\\/]+/, "");
|
|
7588
7586
|
const resolved = path2.resolve(baseDir, cleanRel);
|
|
@@ -7592,45 +7590,6 @@ function safeResolvePath(baseDir, relativePath) {
|
|
|
7592
7590
|
}
|
|
7593
7591
|
return resolved;
|
|
7594
7592
|
}
|
|
7595
|
-
function sendCloudRelayRequest(method, endpoint, payload) {
|
|
7596
|
-
return new Promise((resolve) => {
|
|
7597
|
-
try {
|
|
7598
|
-
const url = new URL(`${CLOUD_RELAY_URL}${endpoint}`);
|
|
7599
|
-
const body = payload ? JSON.stringify(payload) : "";
|
|
7600
|
-
const req = https.request({
|
|
7601
|
-
hostname: url.hostname,
|
|
7602
|
-
port: 443,
|
|
7603
|
-
path: url.pathname + url.search,
|
|
7604
|
-
method,
|
|
7605
|
-
headers: {
|
|
7606
|
-
"Content-Type": "application/json",
|
|
7607
|
-
"Content-Length": Buffer.byteLength(body),
|
|
7608
|
-
"User-Agent": `yap2app-cli/${CLI_VERSION}`
|
|
7609
|
-
},
|
|
7610
|
-
timeout: 6e3
|
|
7611
|
-
}, (res) => {
|
|
7612
|
-
let respData = "";
|
|
7613
|
-
res.on("data", (chunk) => respData += chunk);
|
|
7614
|
-
res.on("end", () => {
|
|
7615
|
-
try {
|
|
7616
|
-
resolve({ ok: res.statusCode >= 200 && res.statusCode < 300, status: res.statusCode, data: JSON.parse(respData || "{}") });
|
|
7617
|
-
} catch {
|
|
7618
|
-
resolve({ ok: false, status: res.statusCode, data: null });
|
|
7619
|
-
}
|
|
7620
|
-
});
|
|
7621
|
-
});
|
|
7622
|
-
req.on("error", () => resolve({ ok: false, status: 0, data: null }));
|
|
7623
|
-
req.on("timeout", () => {
|
|
7624
|
-
req.destroy();
|
|
7625
|
-
resolve({ ok: false, status: 0, data: null });
|
|
7626
|
-
});
|
|
7627
|
-
if (body) req.write(body);
|
|
7628
|
-
req.end();
|
|
7629
|
-
} catch {
|
|
7630
|
-
resolve({ ok: false, status: 0, data: null });
|
|
7631
|
-
}
|
|
7632
|
-
});
|
|
7633
|
-
}
|
|
7634
7593
|
function getCorsHeaders(req) {
|
|
7635
7594
|
const origin = req?.headers?.origin || "*";
|
|
7636
7595
|
const requestedHeaders = req?.headers?.["access-control-request-headers"] || "*";
|
|
@@ -7800,11 +7759,10 @@ server.on("error", (err) => {
|
|
|
7800
7759
|
if (err && err.code === "EADDRINUSE") {
|
|
7801
7760
|
console.log(`
|
|
7802
7761
|
---------------------------------------------------------------`);
|
|
7803
|
-
console.log(`Yap2App Bridge`);
|
|
7804
|
-
console.log(`
|
|
7762
|
+
console.log(`Yap2App Local Bridge v${CLI_VERSION}`);
|
|
7763
|
+
console.log(`Local Endpoint: http://127.0.0.1:${PORT}`);
|
|
7805
7764
|
console.log(`Active Workspace: ${PROJECT_ROOT}`);
|
|
7806
|
-
console.log(`
|
|
7807
|
-
console.log(`Web Studio: ${CLOUD_RELAY_URL}`);
|
|
7765
|
+
console.log(`Status: Already active & ready on port ${PORT}`);
|
|
7808
7766
|
console.log(`---------------------------------------------------------------
|
|
7809
7767
|
`);
|
|
7810
7768
|
console.log(`Bridge is running.`);
|
|
@@ -7819,15 +7777,14 @@ async function startBridge(port = PORT) {
|
|
|
7819
7777
|
server.listen(port, "0.0.0.0", () => {
|
|
7820
7778
|
console.log(`
|
|
7821
7779
|
---------------------------------------------------------------`);
|
|
7822
|
-
console.log(`Yap2App Bridge v${CLI_VERSION}`);
|
|
7780
|
+
console.log(`Yap2App Local Bridge v${CLI_VERSION}`);
|
|
7823
7781
|
console.log(`Local Endpoint: http://127.0.0.1:${port}`);
|
|
7824
7782
|
console.log(`Active Workspace: ${PROJECT_ROOT}`);
|
|
7825
|
-
console.log(`
|
|
7826
|
-
console.log(`Web Studio: ${CLOUD_RELAY_URL}`);
|
|
7783
|
+
console.log(`Web Studio: https://yap2app-dot-cybage-hackathon.uc.r.appspot.com`);
|
|
7827
7784
|
console.log(`---------------------------------------------------------------
|
|
7828
7785
|
`);
|
|
7829
7786
|
console.log(`Bridge is running.`);
|
|
7830
|
-
console.log(`Open Web Studio in your browser to
|
|
7787
|
+
console.log(`Open Web Studio in your browser to automatically connect and sync.`);
|
|
7831
7788
|
console.log(`Press Ctrl/Cmd+C to stop.
|
|
7832
7789
|
`);
|
|
7833
7790
|
});
|
|
@@ -7838,50 +7795,8 @@ async function startBridge(port = PORT) {
|
|
|
7838
7795
|
console.log(` Yap2App will automatically scaffold directories and write files when synced from Web Studio.
|
|
7839
7796
|
`);
|
|
7840
7797
|
}
|
|
7841
|
-
await sendCloudRelayRequest("POST", "/api/v1/bridge/heartbeat", {
|
|
7842
|
-
pair_code: PAIR_CODE,
|
|
7843
|
-
project_name: path2.basename(PROJECT_ROOT),
|
|
7844
|
-
project_root: PROJECT_ROOT,
|
|
7845
|
-
framework: initialContext.framework,
|
|
7846
|
-
context: initialContext,
|
|
7847
|
-
version: CLI_VERSION
|
|
7848
|
-
});
|
|
7849
7798
|
} catch (e) {
|
|
7850
7799
|
}
|
|
7851
|
-
setInterval(async () => {
|
|
7852
|
-
try {
|
|
7853
|
-
const context = await scanCodebase(PROJECT_ROOT);
|
|
7854
|
-
const hbResult = await sendCloudRelayRequest("POST", "/api/v1/bridge/heartbeat", {
|
|
7855
|
-
pair_code: PAIR_CODE,
|
|
7856
|
-
project_name: path2.basename(PROJECT_ROOT),
|
|
7857
|
-
project_root: PROJECT_ROOT,
|
|
7858
|
-
framework: context.framework,
|
|
7859
|
-
context,
|
|
7860
|
-
version: CLI_VERSION
|
|
7861
|
-
});
|
|
7862
|
-
if (hbResult && hbResult.data && hbResult.data.pending_writes_count > 0) {
|
|
7863
|
-
const pollResult = await sendCloudRelayRequest("GET", `/api/v1/bridge/poll-writes?pair_code=${PAIR_CODE}`);
|
|
7864
|
-
const tasks = pollResult.data && pollResult.data.pending_tasks || [];
|
|
7865
|
-
for (const task of tasks) {
|
|
7866
|
-
const written = [];
|
|
7867
|
-
for (const file of task.files || []) {
|
|
7868
|
-
const fullPath = safeResolvePath(PROJECT_ROOT, file.path);
|
|
7869
|
-
await fs2.mkdir(path2.dirname(fullPath), { recursive: true });
|
|
7870
|
-
await fs2.writeFile(fullPath, file.content, "utf8");
|
|
7871
|
-
console.log(` [bridge] Wrote ${file.path}`);
|
|
7872
|
-
written.push(file.path);
|
|
7873
|
-
}
|
|
7874
|
-
await sendCloudRelayRequest("POST", "/api/v1/bridge/complete-write", {
|
|
7875
|
-
task_id: task.task_id,
|
|
7876
|
-
success: true,
|
|
7877
|
-
written,
|
|
7878
|
-
message: `Wrote ${written.length} file(s) directly to ${path2.basename(PROJECT_ROOT)}`
|
|
7879
|
-
});
|
|
7880
|
-
}
|
|
7881
|
-
}
|
|
7882
|
-
} catch {
|
|
7883
|
-
}
|
|
7884
|
-
}, 3500);
|
|
7885
7800
|
}
|
|
7886
7801
|
var isDirectRun = Boolean(typeof process !== "undefined" && process.argv && process.argv[1] && (process.argv[1].endsWith("bridge.js") || process.argv[1].endsWith("bridge")));
|
|
7887
7802
|
if (isDirectRun) {
|
|
@@ -16587,7 +16502,7 @@ Yap2App Codebase Context:
|
|
|
16587
16502
|
console.log(` Files: ${context.discovered_files?.length || 0}`);
|
|
16588
16503
|
console.log(` Components: ${(context.component_names || []).join(", ") || "None"}
|
|
16589
16504
|
`);
|
|
16590
|
-
} else if (command === "init" || command === "install") {
|
|
16505
|
+
} else if (command === "init" || command === "install" || command === "insall") {
|
|
16591
16506
|
const context = await scanCodebase(process.cwd());
|
|
16592
16507
|
console.log(`
|
|
16593
16508
|
\u26A1 Yap2App Workspace Initializer:`);
|
package/bin/cli.js
CHANGED
|
@@ -3552,7 +3552,7 @@ var require_schemes = __commonJS({
|
|
|
3552
3552
|
serialize: httpSerialize
|
|
3553
3553
|
}
|
|
3554
3554
|
);
|
|
3555
|
-
var
|
|
3555
|
+
var https = (
|
|
3556
3556
|
/** @type {SchemeHandler} */
|
|
3557
3557
|
{
|
|
3558
3558
|
scheme: "https",
|
|
@@ -3601,7 +3601,7 @@ var require_schemes = __commonJS({
|
|
|
3601
3601
|
/** @type {Record<SchemeName, SchemeHandler>} */
|
|
3602
3602
|
{
|
|
3603
3603
|
http: http2,
|
|
3604
|
-
https
|
|
3604
|
+
https,
|
|
3605
3605
|
ws,
|
|
3606
3606
|
wss,
|
|
3607
3607
|
urn,
|
|
@@ -7026,7 +7026,6 @@ if (!Promise.allSettled) {
|
|
|
7026
7026
|
|
|
7027
7027
|
// bridge.js
|
|
7028
7028
|
import http from "http";
|
|
7029
|
-
import https from "https";
|
|
7030
7029
|
import fsSync2 from "fs";
|
|
7031
7030
|
import path2 from "path";
|
|
7032
7031
|
import util2 from "util";
|
|
@@ -7580,9 +7579,8 @@ var fs2 = fsSync2.promises || {
|
|
|
7580
7579
|
};
|
|
7581
7580
|
var PORT = Number(process.env.YAP2APP_PORT) || 10420;
|
|
7582
7581
|
var PROJECT_ROOT = process.cwd();
|
|
7583
|
-
var
|
|
7584
|
-
var
|
|
7585
|
-
var CLI_VERSION = "1.1.8";
|
|
7582
|
+
var PAIR_CODE = (process.env.YAP2APP_PAIR_CODE || "Y2A-" + Math.floor(1e3 + Math.random() * 9e3)).toUpperCase();
|
|
7583
|
+
var CLI_VERSION = "1.2.0";
|
|
7586
7584
|
function safeResolvePath(baseDir, relativePath) {
|
|
7587
7585
|
const cleanRel = (relativePath || "").replace(/^[\\\/]+/, "");
|
|
7588
7586
|
const resolved = path2.resolve(baseDir, cleanRel);
|
|
@@ -7592,45 +7590,6 @@ function safeResolvePath(baseDir, relativePath) {
|
|
|
7592
7590
|
}
|
|
7593
7591
|
return resolved;
|
|
7594
7592
|
}
|
|
7595
|
-
function sendCloudRelayRequest(method, endpoint, payload) {
|
|
7596
|
-
return new Promise((resolve) => {
|
|
7597
|
-
try {
|
|
7598
|
-
const url = new URL(`${CLOUD_RELAY_URL}${endpoint}`);
|
|
7599
|
-
const body = payload ? JSON.stringify(payload) : "";
|
|
7600
|
-
const req = https.request({
|
|
7601
|
-
hostname: url.hostname,
|
|
7602
|
-
port: 443,
|
|
7603
|
-
path: url.pathname + url.search,
|
|
7604
|
-
method,
|
|
7605
|
-
headers: {
|
|
7606
|
-
"Content-Type": "application/json",
|
|
7607
|
-
"Content-Length": Buffer.byteLength(body),
|
|
7608
|
-
"User-Agent": `yap2app-cli/${CLI_VERSION}`
|
|
7609
|
-
},
|
|
7610
|
-
timeout: 6e3
|
|
7611
|
-
}, (res) => {
|
|
7612
|
-
let respData = "";
|
|
7613
|
-
res.on("data", (chunk) => respData += chunk);
|
|
7614
|
-
res.on("end", () => {
|
|
7615
|
-
try {
|
|
7616
|
-
resolve({ ok: res.statusCode >= 200 && res.statusCode < 300, status: res.statusCode, data: JSON.parse(respData || "{}") });
|
|
7617
|
-
} catch {
|
|
7618
|
-
resolve({ ok: false, status: res.statusCode, data: null });
|
|
7619
|
-
}
|
|
7620
|
-
});
|
|
7621
|
-
});
|
|
7622
|
-
req.on("error", () => resolve({ ok: false, status: 0, data: null }));
|
|
7623
|
-
req.on("timeout", () => {
|
|
7624
|
-
req.destroy();
|
|
7625
|
-
resolve({ ok: false, status: 0, data: null });
|
|
7626
|
-
});
|
|
7627
|
-
if (body) req.write(body);
|
|
7628
|
-
req.end();
|
|
7629
|
-
} catch {
|
|
7630
|
-
resolve({ ok: false, status: 0, data: null });
|
|
7631
|
-
}
|
|
7632
|
-
});
|
|
7633
|
-
}
|
|
7634
7593
|
function getCorsHeaders(req) {
|
|
7635
7594
|
const origin = req?.headers?.origin || "*";
|
|
7636
7595
|
const requestedHeaders = req?.headers?.["access-control-request-headers"] || "*";
|
|
@@ -7800,11 +7759,10 @@ server.on("error", (err) => {
|
|
|
7800
7759
|
if (err && err.code === "EADDRINUSE") {
|
|
7801
7760
|
console.log(`
|
|
7802
7761
|
---------------------------------------------------------------`);
|
|
7803
|
-
console.log(`Yap2App Bridge`);
|
|
7804
|
-
console.log(`
|
|
7762
|
+
console.log(`Yap2App Local Bridge v${CLI_VERSION}`);
|
|
7763
|
+
console.log(`Local Endpoint: http://127.0.0.1:${PORT}`);
|
|
7805
7764
|
console.log(`Active Workspace: ${PROJECT_ROOT}`);
|
|
7806
|
-
console.log(`
|
|
7807
|
-
console.log(`Web Studio: ${CLOUD_RELAY_URL}`);
|
|
7765
|
+
console.log(`Status: Already active & ready on port ${PORT}`);
|
|
7808
7766
|
console.log(`---------------------------------------------------------------
|
|
7809
7767
|
`);
|
|
7810
7768
|
console.log(`Bridge is running.`);
|
|
@@ -7819,15 +7777,14 @@ async function startBridge(port = PORT) {
|
|
|
7819
7777
|
server.listen(port, "0.0.0.0", () => {
|
|
7820
7778
|
console.log(`
|
|
7821
7779
|
---------------------------------------------------------------`);
|
|
7822
|
-
console.log(`Yap2App Bridge v${CLI_VERSION}`);
|
|
7780
|
+
console.log(`Yap2App Local Bridge v${CLI_VERSION}`);
|
|
7823
7781
|
console.log(`Local Endpoint: http://127.0.0.1:${port}`);
|
|
7824
7782
|
console.log(`Active Workspace: ${PROJECT_ROOT}`);
|
|
7825
|
-
console.log(`
|
|
7826
|
-
console.log(`Web Studio: ${CLOUD_RELAY_URL}`);
|
|
7783
|
+
console.log(`Web Studio: https://yap2app-dot-cybage-hackathon.uc.r.appspot.com`);
|
|
7827
7784
|
console.log(`---------------------------------------------------------------
|
|
7828
7785
|
`);
|
|
7829
7786
|
console.log(`Bridge is running.`);
|
|
7830
|
-
console.log(`Open Web Studio in your browser to
|
|
7787
|
+
console.log(`Open Web Studio in your browser to automatically connect and sync.`);
|
|
7831
7788
|
console.log(`Press Ctrl/Cmd+C to stop.
|
|
7832
7789
|
`);
|
|
7833
7790
|
});
|
|
@@ -7838,50 +7795,8 @@ async function startBridge(port = PORT) {
|
|
|
7838
7795
|
console.log(` Yap2App will automatically scaffold directories and write files when synced from Web Studio.
|
|
7839
7796
|
`);
|
|
7840
7797
|
}
|
|
7841
|
-
await sendCloudRelayRequest("POST", "/api/v1/bridge/heartbeat", {
|
|
7842
|
-
pair_code: PAIR_CODE,
|
|
7843
|
-
project_name: path2.basename(PROJECT_ROOT),
|
|
7844
|
-
project_root: PROJECT_ROOT,
|
|
7845
|
-
framework: initialContext.framework,
|
|
7846
|
-
context: initialContext,
|
|
7847
|
-
version: CLI_VERSION
|
|
7848
|
-
});
|
|
7849
7798
|
} catch (e) {
|
|
7850
7799
|
}
|
|
7851
|
-
setInterval(async () => {
|
|
7852
|
-
try {
|
|
7853
|
-
const context = await scanCodebase(PROJECT_ROOT);
|
|
7854
|
-
const hbResult = await sendCloudRelayRequest("POST", "/api/v1/bridge/heartbeat", {
|
|
7855
|
-
pair_code: PAIR_CODE,
|
|
7856
|
-
project_name: path2.basename(PROJECT_ROOT),
|
|
7857
|
-
project_root: PROJECT_ROOT,
|
|
7858
|
-
framework: context.framework,
|
|
7859
|
-
context,
|
|
7860
|
-
version: CLI_VERSION
|
|
7861
|
-
});
|
|
7862
|
-
if (hbResult && hbResult.data && hbResult.data.pending_writes_count > 0) {
|
|
7863
|
-
const pollResult = await sendCloudRelayRequest("GET", `/api/v1/bridge/poll-writes?pair_code=${PAIR_CODE}`);
|
|
7864
|
-
const tasks = pollResult.data && pollResult.data.pending_tasks || [];
|
|
7865
|
-
for (const task of tasks) {
|
|
7866
|
-
const written = [];
|
|
7867
|
-
for (const file of task.files || []) {
|
|
7868
|
-
const fullPath = safeResolvePath(PROJECT_ROOT, file.path);
|
|
7869
|
-
await fs2.mkdir(path2.dirname(fullPath), { recursive: true });
|
|
7870
|
-
await fs2.writeFile(fullPath, file.content, "utf8");
|
|
7871
|
-
console.log(` [bridge] Wrote ${file.path}`);
|
|
7872
|
-
written.push(file.path);
|
|
7873
|
-
}
|
|
7874
|
-
await sendCloudRelayRequest("POST", "/api/v1/bridge/complete-write", {
|
|
7875
|
-
task_id: task.task_id,
|
|
7876
|
-
success: true,
|
|
7877
|
-
written,
|
|
7878
|
-
message: `Wrote ${written.length} file(s) directly to ${path2.basename(PROJECT_ROOT)}`
|
|
7879
|
-
});
|
|
7880
|
-
}
|
|
7881
|
-
}
|
|
7882
|
-
} catch {
|
|
7883
|
-
}
|
|
7884
|
-
}, 3500);
|
|
7885
7800
|
}
|
|
7886
7801
|
var isDirectRun = Boolean(typeof process !== "undefined" && process.argv && process.argv[1] && (process.argv[1].endsWith("bridge.js") || process.argv[1].endsWith("bridge")));
|
|
7887
7802
|
if (isDirectRun) {
|
|
@@ -16587,7 +16502,7 @@ Yap2App Codebase Context:
|
|
|
16587
16502
|
console.log(` Files: ${context.discovered_files?.length || 0}`);
|
|
16588
16503
|
console.log(` Components: ${(context.component_names || []).join(", ") || "None"}
|
|
16589
16504
|
`);
|
|
16590
|
-
} else if (command === "init" || command === "install") {
|
|
16505
|
+
} else if (command === "init" || command === "install" || command === "insall") {
|
|
16591
16506
|
const context = await scanCodebase(process.cwd());
|
|
16592
16507
|
console.log(`
|
|
16593
16508
|
\u26A1 Yap2App Workspace Initializer:`);
|
package/bridge.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import http from 'http';
|
|
2
|
-
import https from 'https';
|
|
3
2
|
import fsSync from 'fs';
|
|
4
3
|
import path from 'path';
|
|
5
4
|
import util from 'util';
|
|
@@ -15,9 +14,8 @@ const fs = fsSync.promises || {
|
|
|
15
14
|
|
|
16
15
|
const PORT = Number(process.env.YAP2APP_PORT) || 10420;
|
|
17
16
|
const PROJECT_ROOT = process.cwd();
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const CLI_VERSION = '1.1.8';
|
|
17
|
+
const PAIR_CODE = (process.env.YAP2APP_PAIR_CODE || ('Y2A-' + Math.floor(1000 + Math.random() * 9000))).toUpperCase();
|
|
18
|
+
const CLI_VERSION = '1.2.0';
|
|
21
19
|
|
|
22
20
|
/**
|
|
23
21
|
* Validates and resolves relative file paths strictly inside PROJECT_ROOT.
|
|
@@ -33,44 +31,6 @@ function safeResolvePath(baseDir, relativePath) {
|
|
|
33
31
|
return resolved;
|
|
34
32
|
}
|
|
35
33
|
|
|
36
|
-
// Helper to send outbound HTTPS requests to the Yap2App Cloud Relay
|
|
37
|
-
function sendCloudRelayRequest(method, endpoint, payload) {
|
|
38
|
-
return new Promise((resolve) => {
|
|
39
|
-
try {
|
|
40
|
-
const url = new URL(`${CLOUD_RELAY_URL}${endpoint}`);
|
|
41
|
-
const body = payload ? JSON.stringify(payload) : '';
|
|
42
|
-
const req = https.request({
|
|
43
|
-
hostname: url.hostname,
|
|
44
|
-
port: 443,
|
|
45
|
-
path: url.pathname + url.search,
|
|
46
|
-
method: method,
|
|
47
|
-
headers: {
|
|
48
|
-
'Content-Type': 'application/json',
|
|
49
|
-
'Content-Length': Buffer.byteLength(body),
|
|
50
|
-
'User-Agent': `yap2app-cli/${CLI_VERSION}`
|
|
51
|
-
},
|
|
52
|
-
timeout: 6000
|
|
53
|
-
}, (res) => {
|
|
54
|
-
let respData = '';
|
|
55
|
-
res.on('data', chunk => respData += chunk);
|
|
56
|
-
res.on('end', () => {
|
|
57
|
-
try {
|
|
58
|
-
resolve({ ok: res.statusCode >= 200 && res.statusCode < 300, status: res.statusCode, data: JSON.parse(respData || '{}') });
|
|
59
|
-
} catch {
|
|
60
|
-
resolve({ ok: false, status: res.statusCode, data: null });
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
req.on('error', () => resolve({ ok: false, status: 0, data: null }));
|
|
65
|
-
req.on('timeout', () => { req.destroy(); resolve({ ok: false, status: 0, data: null }); });
|
|
66
|
-
if (body) req.write(body);
|
|
67
|
-
req.end();
|
|
68
|
-
} catch {
|
|
69
|
-
resolve({ ok: false, status: 0, data: null });
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
34
|
// Bulletproof W3C Private Network Access (PNA) and Dynamic Origin CORS Headers
|
|
75
35
|
function getCorsHeaders(req) {
|
|
76
36
|
const origin = req?.headers?.origin || '*';
|
|
@@ -281,11 +241,10 @@ const server = http.createServer(async (req, res) => {
|
|
|
281
241
|
server.on('error', (err) => {
|
|
282
242
|
if (err && err.code === 'EADDRINUSE') {
|
|
283
243
|
console.log(`\n---------------------------------------------------------------`);
|
|
284
|
-
console.log(`Yap2App Bridge`);
|
|
285
|
-
console.log(`
|
|
244
|
+
console.log(`Yap2App Local Bridge v${CLI_VERSION}`);
|
|
245
|
+
console.log(`Local Endpoint: http://127.0.0.1:${PORT}`);
|
|
286
246
|
console.log(`Active Workspace: ${PROJECT_ROOT}`);
|
|
287
|
-
console.log(`
|
|
288
|
-
console.log(`Web Studio: ${CLOUD_RELAY_URL}`);
|
|
247
|
+
console.log(`Status: Already active & ready on port ${PORT}`);
|
|
289
248
|
console.log(`---------------------------------------------------------------\n`);
|
|
290
249
|
console.log(`Bridge is running.`);
|
|
291
250
|
console.log(`Open Web Studio in your browser to sync components to this workspace.`);
|
|
@@ -298,70 +257,24 @@ server.on('error', (err) => {
|
|
|
298
257
|
export async function startBridge(port = PORT) {
|
|
299
258
|
server.listen(port, '0.0.0.0', () => {
|
|
300
259
|
console.log(`\n---------------------------------------------------------------`);
|
|
301
|
-
console.log(`Yap2App Bridge v${CLI_VERSION}`);
|
|
260
|
+
console.log(`Yap2App Local Bridge v${CLI_VERSION}`);
|
|
302
261
|
console.log(`Local Endpoint: http://127.0.0.1:${port}`);
|
|
303
262
|
console.log(`Active Workspace: ${PROJECT_ROOT}`);
|
|
304
|
-
console.log(`
|
|
305
|
-
console.log(`Web Studio: ${CLOUD_RELAY_URL}`);
|
|
263
|
+
console.log(`Web Studio: https://yap2app-dot-cybage-hackathon.uc.r.appspot.com`);
|
|
306
264
|
console.log(`---------------------------------------------------------------\n`);
|
|
307
265
|
console.log(`Bridge is running.`);
|
|
308
|
-
console.log(`Open Web Studio in your browser to
|
|
266
|
+
console.log(`Open Web Studio in your browser to automatically connect and sync.`);
|
|
309
267
|
console.log(`Press Ctrl/Cmd+C to stop.\n`);
|
|
310
268
|
});
|
|
311
269
|
|
|
312
|
-
// Initial scan
|
|
270
|
+
// Initial scan notice
|
|
313
271
|
try {
|
|
314
272
|
const initialContext = await scanCodebase(PROJECT_ROOT);
|
|
315
273
|
if (initialContext && initialContext.total_files_count === 0) {
|
|
316
274
|
console.log(` ℹ️ Fresh workspace detected (0 code files).`);
|
|
317
275
|
console.log(` Yap2App will automatically scaffold directories and write files when synced from Web Studio.\n`);
|
|
318
276
|
}
|
|
319
|
-
await sendCloudRelayRequest('POST', '/api/v1/bridge/heartbeat', {
|
|
320
|
-
pair_code: PAIR_CODE,
|
|
321
|
-
project_name: path.basename(PROJECT_ROOT),
|
|
322
|
-
project_root: PROJECT_ROOT,
|
|
323
|
-
framework: initialContext.framework,
|
|
324
|
-
context: initialContext,
|
|
325
|
-
version: CLI_VERSION
|
|
326
|
-
});
|
|
327
277
|
} catch (e) {}
|
|
328
|
-
|
|
329
|
-
// Periodic Cloud Relay heartbeat & write execution loop (every 3.5 seconds)
|
|
330
|
-
setInterval(async () => {
|
|
331
|
-
try {
|
|
332
|
-
const context = await scanCodebase(PROJECT_ROOT);
|
|
333
|
-
const hbResult = await sendCloudRelayRequest('POST', '/api/v1/bridge/heartbeat', {
|
|
334
|
-
pair_code: PAIR_CODE,
|
|
335
|
-
project_name: path.basename(PROJECT_ROOT),
|
|
336
|
-
project_root: PROJECT_ROOT,
|
|
337
|
-
framework: context.framework,
|
|
338
|
-
context: context,
|
|
339
|
-
version: CLI_VERSION
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
// If pending write tasks, fetch and execute them on local disk
|
|
343
|
-
if (hbResult && hbResult.data && hbResult.data.pending_writes_count > 0) {
|
|
344
|
-
const pollResult = await sendCloudRelayRequest('GET', `/api/v1/bridge/poll-writes?pair_code=${PAIR_CODE}`);
|
|
345
|
-
const tasks = (pollResult.data && pollResult.data.pending_tasks) || [];
|
|
346
|
-
for (const task of tasks) {
|
|
347
|
-
const written = [];
|
|
348
|
-
for (const file of (task.files || [])) {
|
|
349
|
-
const fullPath = safeResolvePath(PROJECT_ROOT, file.path);
|
|
350
|
-
await fs.mkdir(path.dirname(fullPath), { recursive: true });
|
|
351
|
-
await fs.writeFile(fullPath, file.content, 'utf8');
|
|
352
|
-
console.log(` [bridge] Wrote ${file.path}`);
|
|
353
|
-
written.push(file.path);
|
|
354
|
-
}
|
|
355
|
-
await sendCloudRelayRequest('POST', '/api/v1/bridge/complete-write', {
|
|
356
|
-
task_id: task.task_id,
|
|
357
|
-
success: true,
|
|
358
|
-
written,
|
|
359
|
-
message: `Wrote ${written.length} file(s) directly to ${path.basename(PROJECT_ROOT)}`
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
} catch {}
|
|
364
|
-
}, 3500);
|
|
365
278
|
}
|
|
366
279
|
|
|
367
280
|
// Direct execution
|