yap2app 1.2.2 → 1.2.4

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 CHANGED
@@ -1,4 +1,6 @@
1
- import { createRequire } from 'module'; const require = createRequire(import.meta.url);
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'module';
3
+ const require = createRequire(import.meta.url);
2
4
  var __create = Object.create;
3
5
  var __defProp = Object.defineProperty;
4
6
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -7579,8 +7581,34 @@ var fs2 = fsSync2.promises || {
7579
7581
  };
7580
7582
  var PORT = Number(process.env.YAP2APP_PORT) || 10420;
7581
7583
  var PROJECT_ROOT = process.cwd();
7582
- var PAIR_CODE = (process.env.YAP2APP_PAIR_CODE || "Y2A-" + Math.floor(1e3 + Math.random() * 9e3)).toUpperCase();
7583
- var CLI_VERSION = "1.2.2";
7584
+ var CLI_VERSION = "1.2.4";
7585
+ function resolvePairCode() {
7586
+ if (process.env.YAP2APP_PAIR_CODE) {
7587
+ return process.env.YAP2APP_PAIR_CODE.trim().toUpperCase();
7588
+ }
7589
+ const configDir = path2.join(PROJECT_ROOT, ".yap2app");
7590
+ const configFile = path2.join(configDir, "bridge.json");
7591
+ try {
7592
+ if (fsSync2.existsSync(configFile)) {
7593
+ const raw = fsSync2.readFileSync(configFile, "utf8");
7594
+ const data = JSON.parse(raw);
7595
+ if (data.pair_code && typeof data.pair_code === "string") {
7596
+ return data.pair_code.trim().toUpperCase();
7597
+ }
7598
+ }
7599
+ } catch (e) {
7600
+ }
7601
+ const newCode = ("Y2A-" + Math.floor(1e3 + Math.random() * 9e3)).toUpperCase();
7602
+ try {
7603
+ if (!fsSync2.existsSync(configDir)) {
7604
+ fsSync2.mkdirSync(configDir, { recursive: true });
7605
+ }
7606
+ fsSync2.writeFileSync(configFile, JSON.stringify({ pair_code: newCode, created_at: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf8");
7607
+ } catch (e) {
7608
+ }
7609
+ return newCode;
7610
+ }
7611
+ var PAIR_CODE = resolvePairCode();
7584
7612
  function getGitUserEmail() {
7585
7613
  try {
7586
7614
  const email2 = execSync("git config user.email", { encoding: "utf8", stdio: ["pipe", "pipe", "ignore"] }).trim();
@@ -7607,18 +7635,23 @@ function safeResolvePath(baseDir, relativePath) {
7607
7635
  return resolved;
7608
7636
  }
7609
7637
  function getCorsHeaders(req) {
7610
- const origin = req?.headers?.origin || "*";
7638
+ const origin = req?.headers?.origin;
7611
7639
  const requestedHeaders = req?.headers?.["access-control-request-headers"] || "*";
7612
- return {
7613
- "Access-Control-Allow-Origin": origin,
7640
+ const headers = {
7614
7641
  "Access-Control-Allow-Methods": "GET, POST, OPTIONS, PUT, DELETE, HEAD, PATCH",
7615
- "Access-Control-Allow-Headers": requestedHeaders === "*" ? "Content-Type, Authorization, Access-Control-Request-Private-Network, X-Requested-With, Accept, Origin, *" : requestedHeaders,
7642
+ "Access-Control-Allow-Headers": requestedHeaders === "*" ? "Content-Type, Authorization, Access-Control-Request-Private-Network, X-Requested-With, Accept, Origin, Cache-Control, Pragma, *" : requestedHeaders,
7616
7643
  "Access-Control-Allow-Private-Network": "true",
7617
- "Access-Control-Allow-Credentials": "true",
7618
7644
  "Access-Control-Max-Age": "86400",
7619
7645
  "Vary": "Origin, Access-Control-Request-Headers, Access-Control-Request-Private-Network",
7620
7646
  "Content-Type": "application/json"
7621
7647
  };
7648
+ if (origin) {
7649
+ headers["Access-Control-Allow-Origin"] = origin;
7650
+ headers["Access-Control-Allow-Credentials"] = "true";
7651
+ } else {
7652
+ headers["Access-Control-Allow-Origin"] = "*";
7653
+ }
7654
+ return headers;
7622
7655
  }
7623
7656
  function computeDiff(originalText, newText) {
7624
7657
  const originalLines = originalText ? originalText.split("\n") : [];
@@ -7772,7 +7805,9 @@ var server = http.createServer(async (req, res) => {
7772
7805
  res.end(JSON.stringify({ error: "Endpoint Not Found", path: pathname }));
7773
7806
  });
7774
7807
  var CLOUD_URL = process.env.YAP2APP_CLOUD_URL || "https://yap2app-dot-cybage-hackathon.uc.r.appspot.com";
7808
+ var isShuttingDown = false;
7775
7809
  async function sendCloudHeartbeat() {
7810
+ if (isShuttingDown) return;
7776
7811
  try {
7777
7812
  const context = await scanCodebase(PROJECT_ROOT);
7778
7813
  const payload = {
@@ -7798,6 +7833,32 @@ async function sendCloudHeartbeat() {
7798
7833
  } catch (err) {
7799
7834
  }
7800
7835
  }
7836
+ async function gracefulShutdown(signal = "SIGINT") {
7837
+ if (isShuttingDown) return;
7838
+ isShuttingDown = true;
7839
+ console.log(`
7840
+ [bridge] Disconnecting bridge (${signal}). Informing cloud relay...`);
7841
+ try {
7842
+ const controller = new AbortController();
7843
+ const timeoutId = setTimeout(() => controller.abort(), 1500);
7844
+ await fetch(`${CLOUD_URL}/api/v1/bridge/disconnect`, {
7845
+ method: "POST",
7846
+ headers: { "Content-Type": "application/json" },
7847
+ body: JSON.stringify({ pair_code: PAIR_CODE }),
7848
+ signal: controller.signal
7849
+ }).catch(() => {
7850
+ });
7851
+ clearTimeout(timeoutId);
7852
+ } catch (e) {
7853
+ }
7854
+ try {
7855
+ server.close();
7856
+ } catch (e) {
7857
+ }
7858
+ process.exit(0);
7859
+ }
7860
+ process.once("SIGINT", () => gracefulShutdown("SIGINT"));
7861
+ process.once("SIGTERM", () => gracefulShutdown("SIGTERM"));
7801
7862
  async function pollAndExecuteCloudWrites() {
7802
7863
  try {
7803
7864
  const res = await fetch(`${CLOUD_URL}/api/v1/bridge/poll-writes?pair_code=${encodeURIComponent(PAIR_CODE)}`);
package/bin/cli.js CHANGED
@@ -1,4 +1,6 @@
1
- import { createRequire } from 'module'; const require = createRequire(import.meta.url);
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'module';
3
+ const require = createRequire(import.meta.url);
2
4
  var __create = Object.create;
3
5
  var __defProp = Object.defineProperty;
4
6
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -7579,8 +7581,34 @@ var fs2 = fsSync2.promises || {
7579
7581
  };
7580
7582
  var PORT = Number(process.env.YAP2APP_PORT) || 10420;
7581
7583
  var PROJECT_ROOT = process.cwd();
7582
- var PAIR_CODE = (process.env.YAP2APP_PAIR_CODE || "Y2A-" + Math.floor(1e3 + Math.random() * 9e3)).toUpperCase();
7583
- var CLI_VERSION = "1.2.2";
7584
+ var CLI_VERSION = "1.2.4";
7585
+ function resolvePairCode() {
7586
+ if (process.env.YAP2APP_PAIR_CODE) {
7587
+ return process.env.YAP2APP_PAIR_CODE.trim().toUpperCase();
7588
+ }
7589
+ const configDir = path2.join(PROJECT_ROOT, ".yap2app");
7590
+ const configFile = path2.join(configDir, "bridge.json");
7591
+ try {
7592
+ if (fsSync2.existsSync(configFile)) {
7593
+ const raw = fsSync2.readFileSync(configFile, "utf8");
7594
+ const data = JSON.parse(raw);
7595
+ if (data.pair_code && typeof data.pair_code === "string") {
7596
+ return data.pair_code.trim().toUpperCase();
7597
+ }
7598
+ }
7599
+ } catch (e) {
7600
+ }
7601
+ const newCode = ("Y2A-" + Math.floor(1e3 + Math.random() * 9e3)).toUpperCase();
7602
+ try {
7603
+ if (!fsSync2.existsSync(configDir)) {
7604
+ fsSync2.mkdirSync(configDir, { recursive: true });
7605
+ }
7606
+ fsSync2.writeFileSync(configFile, JSON.stringify({ pair_code: newCode, created_at: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf8");
7607
+ } catch (e) {
7608
+ }
7609
+ return newCode;
7610
+ }
7611
+ var PAIR_CODE = resolvePairCode();
7584
7612
  function getGitUserEmail() {
7585
7613
  try {
7586
7614
  const email2 = execSync("git config user.email", { encoding: "utf8", stdio: ["pipe", "pipe", "ignore"] }).trim();
@@ -7607,18 +7635,23 @@ function safeResolvePath(baseDir, relativePath) {
7607
7635
  return resolved;
7608
7636
  }
7609
7637
  function getCorsHeaders(req) {
7610
- const origin = req?.headers?.origin || "*";
7638
+ const origin = req?.headers?.origin;
7611
7639
  const requestedHeaders = req?.headers?.["access-control-request-headers"] || "*";
7612
- return {
7613
- "Access-Control-Allow-Origin": origin,
7640
+ const headers = {
7614
7641
  "Access-Control-Allow-Methods": "GET, POST, OPTIONS, PUT, DELETE, HEAD, PATCH",
7615
- "Access-Control-Allow-Headers": requestedHeaders === "*" ? "Content-Type, Authorization, Access-Control-Request-Private-Network, X-Requested-With, Accept, Origin, *" : requestedHeaders,
7642
+ "Access-Control-Allow-Headers": requestedHeaders === "*" ? "Content-Type, Authorization, Access-Control-Request-Private-Network, X-Requested-With, Accept, Origin, Cache-Control, Pragma, *" : requestedHeaders,
7616
7643
  "Access-Control-Allow-Private-Network": "true",
7617
- "Access-Control-Allow-Credentials": "true",
7618
7644
  "Access-Control-Max-Age": "86400",
7619
7645
  "Vary": "Origin, Access-Control-Request-Headers, Access-Control-Request-Private-Network",
7620
7646
  "Content-Type": "application/json"
7621
7647
  };
7648
+ if (origin) {
7649
+ headers["Access-Control-Allow-Origin"] = origin;
7650
+ headers["Access-Control-Allow-Credentials"] = "true";
7651
+ } else {
7652
+ headers["Access-Control-Allow-Origin"] = "*";
7653
+ }
7654
+ return headers;
7622
7655
  }
7623
7656
  function computeDiff(originalText, newText) {
7624
7657
  const originalLines = originalText ? originalText.split("\n") : [];
@@ -7772,7 +7805,9 @@ var server = http.createServer(async (req, res) => {
7772
7805
  res.end(JSON.stringify({ error: "Endpoint Not Found", path: pathname }));
7773
7806
  });
7774
7807
  var CLOUD_URL = process.env.YAP2APP_CLOUD_URL || "https://yap2app-dot-cybage-hackathon.uc.r.appspot.com";
7808
+ var isShuttingDown = false;
7775
7809
  async function sendCloudHeartbeat() {
7810
+ if (isShuttingDown) return;
7776
7811
  try {
7777
7812
  const context = await scanCodebase(PROJECT_ROOT);
7778
7813
  const payload = {
@@ -7798,6 +7833,32 @@ async function sendCloudHeartbeat() {
7798
7833
  } catch (err) {
7799
7834
  }
7800
7835
  }
7836
+ async function gracefulShutdown(signal = "SIGINT") {
7837
+ if (isShuttingDown) return;
7838
+ isShuttingDown = true;
7839
+ console.log(`
7840
+ [bridge] Disconnecting bridge (${signal}). Informing cloud relay...`);
7841
+ try {
7842
+ const controller = new AbortController();
7843
+ const timeoutId = setTimeout(() => controller.abort(), 1500);
7844
+ await fetch(`${CLOUD_URL}/api/v1/bridge/disconnect`, {
7845
+ method: "POST",
7846
+ headers: { "Content-Type": "application/json" },
7847
+ body: JSON.stringify({ pair_code: PAIR_CODE }),
7848
+ signal: controller.signal
7849
+ }).catch(() => {
7850
+ });
7851
+ clearTimeout(timeoutId);
7852
+ } catch (e) {
7853
+ }
7854
+ try {
7855
+ server.close();
7856
+ } catch (e) {
7857
+ }
7858
+ process.exit(0);
7859
+ }
7860
+ process.once("SIGINT", () => gracefulShutdown("SIGINT"));
7861
+ process.once("SIGTERM", () => gracefulShutdown("SIGTERM"));
7801
7862
  async function pollAndExecuteCloudWrites() {
7802
7863
  try {
7803
7864
  const res = await fetch(`${CLOUD_URL}/api/v1/bridge/poll-writes?pair_code=${encodeURIComponent(PAIR_CODE)}`);
package/bridge.js CHANGED
@@ -15,8 +15,35 @@ const fs = fsSync.promises || {
15
15
 
16
16
  const PORT = Number(process.env.YAP2APP_PORT) || 10420;
17
17
  const PROJECT_ROOT = process.cwd();
18
- const PAIR_CODE = (process.env.YAP2APP_PAIR_CODE || ('Y2A-' + Math.floor(1000 + Math.random() * 9000))).toUpperCase();
19
- const CLI_VERSION = '1.2.2';
18
+ const CLI_VERSION = '1.2.4';
19
+
20
+ function resolvePairCode() {
21
+ if (process.env.YAP2APP_PAIR_CODE) {
22
+ return process.env.YAP2APP_PAIR_CODE.trim().toUpperCase();
23
+ }
24
+ const configDir = path.join(PROJECT_ROOT, '.yap2app');
25
+ const configFile = path.join(configDir, 'bridge.json');
26
+ try {
27
+ if (fsSync.existsSync(configFile)) {
28
+ const raw = fsSync.readFileSync(configFile, 'utf8');
29
+ const data = JSON.parse(raw);
30
+ if (data.pair_code && typeof data.pair_code === 'string') {
31
+ return data.pair_code.trim().toUpperCase();
32
+ }
33
+ }
34
+ } catch (e) {}
35
+
36
+ const newCode = ('Y2A-' + Math.floor(1000 + Math.random() * 9000)).toUpperCase();
37
+ try {
38
+ if (!fsSync.existsSync(configDir)) {
39
+ fsSync.mkdirSync(configDir, { recursive: true });
40
+ }
41
+ fsSync.writeFileSync(configFile, JSON.stringify({ pair_code: newCode, created_at: new Date().toISOString() }, null, 2), 'utf8');
42
+ } catch (e) {}
43
+ return newCode;
44
+ }
45
+
46
+ const PAIR_CODE = resolvePairCode();
20
47
 
21
48
  function getGitUserEmail() {
22
49
  try {
@@ -53,18 +80,25 @@ function safeResolvePath(baseDir, relativePath) {
53
80
 
54
81
  // Bulletproof W3C Private Network Access (PNA) and Dynamic Origin CORS Headers
55
82
  function getCorsHeaders(req) {
56
- const origin = req?.headers?.origin || '*';
83
+ const origin = req?.headers?.origin;
57
84
  const requestedHeaders = req?.headers?.['access-control-request-headers'] || '*';
58
- return {
59
- 'Access-Control-Allow-Origin': origin,
85
+ const headers = {
60
86
  'Access-Control-Allow-Methods': 'GET, POST, OPTIONS, PUT, DELETE, HEAD, PATCH',
61
- 'Access-Control-Allow-Headers': requestedHeaders === '*' ? 'Content-Type, Authorization, Access-Control-Request-Private-Network, X-Requested-With, Accept, Origin, *' : requestedHeaders,
87
+ 'Access-Control-Allow-Headers': requestedHeaders === '*'
88
+ ? 'Content-Type, Authorization, Access-Control-Request-Private-Network, X-Requested-With, Accept, Origin, Cache-Control, Pragma, *'
89
+ : requestedHeaders,
62
90
  'Access-Control-Allow-Private-Network': 'true',
63
- 'Access-Control-Allow-Credentials': 'true',
64
91
  'Access-Control-Max-Age': '86400',
65
92
  'Vary': 'Origin, Access-Control-Request-Headers, Access-Control-Request-Private-Network',
66
93
  'Content-Type': 'application/json'
67
94
  };
95
+ if (origin) {
96
+ headers['Access-Control-Allow-Origin'] = origin;
97
+ headers['Access-Control-Allow-Credentials'] = 'true';
98
+ } else {
99
+ headers['Access-Control-Allow-Origin'] = '*';
100
+ }
101
+ return headers;
68
102
  }
69
103
 
70
104
  /**
@@ -259,7 +293,10 @@ const server = http.createServer(async (req, res) => {
259
293
 
260
294
  const CLOUD_URL = process.env.YAP2APP_CLOUD_URL || 'https://yap2app-dot-cybage-hackathon.uc.r.appspot.com';
261
295
 
296
+ let isShuttingDown = false;
297
+
262
298
  async function sendCloudHeartbeat() {
299
+ if (isShuttingDown) return;
263
300
  try {
264
301
  const context = await scanCodebase(PROJECT_ROOT);
265
302
  const payload = {
@@ -289,6 +326,30 @@ async function sendCloudHeartbeat() {
289
326
  }
290
327
  }
291
328
 
329
+ export async function gracefulShutdown(signal = 'SIGINT') {
330
+ if (isShuttingDown) return;
331
+ isShuttingDown = true;
332
+ console.log(`\n [bridge] Disconnecting bridge (${signal}). Informing cloud relay...`);
333
+ try {
334
+ const controller = new AbortController();
335
+ const timeoutId = setTimeout(() => controller.abort(), 1500);
336
+ await fetch(`${CLOUD_URL}/api/v1/bridge/disconnect`, {
337
+ method: 'POST',
338
+ headers: { 'Content-Type': 'application/json' },
339
+ body: JSON.stringify({ pair_code: PAIR_CODE }),
340
+ signal: controller.signal
341
+ }).catch(() => {});
342
+ clearTimeout(timeoutId);
343
+ } catch (e) {}
344
+ try {
345
+ server.close();
346
+ } catch (e) {}
347
+ process.exit(0);
348
+ }
349
+
350
+ process.once('SIGINT', () => gracefulShutdown('SIGINT'));
351
+ process.once('SIGTERM', () => gracefulShutdown('SIGTERM'));
352
+
292
353
  async function pollAndExecuteCloudWrites() {
293
354
  try {
294
355
  const res = await fetch(`${CLOUD_URL}/api/v1/bridge/poll-writes?pair_code=${encodeURIComponent(PAIR_CODE)}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yap2app",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
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,8 +24,8 @@
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",
28
- "start": "node ./bin/cli.js start",
27
+ "build": "npx esbuild bin/cli-esm.js --bundle --platform=node --target=node18 --format=esm --banner:js=\"#!/usr/bin/env node\nimport { createRequire } from 'module';\nconst require = createRequire(import.meta.url);\" --outfile=bin/cli.bundle.js && cp bin/cli.bundle.js bin/cli.js && chmod +x bin/cli.js bin/cli.bundle.js",
28
+ "start": "./bin/cli.js start",
29
29
  "bridge": "node ./bin/cli.js bridge",
30
30
  "mcp": "node ./bin/cli.js mcp",
31
31
  "scan": "node ./bin/cli.js scan"