@vercel/go 3.8.0 → 3.9.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.
Binary file
Binary file
package/dist/index.js CHANGED
@@ -1917,9 +1917,9 @@ var require_end_of_stream = __commonJS({
1917
1917
  }
1918
1918
  });
1919
1919
 
1920
- // ../../node_modules/.pnpm/pump@3.0.2/node_modules/pump/index.js
1920
+ // ../../node_modules/.pnpm/pump@3.0.4/node_modules/pump/index.js
1921
1921
  var require_pump = __commonJS({
1922
- "../../node_modules/.pnpm/pump@3.0.2/node_modules/pump/index.js"(exports, module2) {
1922
+ "../../node_modules/.pnpm/pump@3.0.4/node_modules/pump/index.js"(exports, module2) {
1923
1923
  var once2 = require_once();
1924
1924
  var eos = require_end_of_stream();
1925
1925
  var fs3;
@@ -1929,7 +1929,7 @@ var require_pump = __commonJS({
1929
1929
  }
1930
1930
  var noop = function() {
1931
1931
  };
1932
- var ancient = /^v?\.0/.test(process.version);
1932
+ var ancient = typeof process === "undefined" ? false : /^v?\.0/.test(process.version);
1933
1933
  var isFn = function(fn2) {
1934
1934
  return typeof fn2 === "function";
1935
1935
  };
@@ -3453,13 +3453,13 @@ var require_clone = __commonJS({
3453
3453
  if (obj === null || typeof obj !== "object")
3454
3454
  return obj;
3455
3455
  if (obj instanceof Object)
3456
- var copy4 = { __proto__: getPrototypeOf(obj) };
3456
+ var copy3 = { __proto__: getPrototypeOf(obj) };
3457
3457
  else
3458
- var copy4 = /* @__PURE__ */ Object.create(null);
3458
+ var copy3 = /* @__PURE__ */ Object.create(null);
3459
3459
  Object.getOwnPropertyNames(obj).forEach(function(key) {
3460
- Object.defineProperty(copy4, key, Object.getOwnPropertyDescriptor(obj, key));
3460
+ Object.defineProperty(copy3, key, Object.getOwnPropertyDescriptor(obj, key));
3461
3461
  });
3462
- return copy4;
3462
+ return copy3;
3463
3463
  }
3464
3464
  }
3465
3465
  });
@@ -3549,8 +3549,8 @@ var require_graceful_fs = __commonJS({
3549
3549
  fs4.createReadStream = createReadStream;
3550
3550
  fs4.createWriteStream = createWriteStream2;
3551
3551
  var fs$readFile = fs4.readFile;
3552
- fs4.readFile = readFile4;
3553
- function readFile4(path, options, cb) {
3552
+ fs4.readFile = readFile3;
3553
+ function readFile3(path, options, cb) {
3554
3554
  if (typeof options === "function")
3555
3555
  cb = options, options = null;
3556
3556
  return go$readFile(path, options, cb);
@@ -4376,7 +4376,7 @@ var require_copy = __commonJS({
4376
4376
  var pathExists5 = require_path_exists().pathExists;
4377
4377
  var utimes = require_utimes().utimesMillis;
4378
4378
  var notExist = Symbol("notExist");
4379
- function copy4(src, dest, opts, cb) {
4379
+ function copy3(src, dest, opts, cb) {
4380
4380
  if (typeof opts === "function" && !cb) {
4381
4381
  cb = opts;
4382
4382
  opts = {};
@@ -4602,7 +4602,7 @@ var require_copy = __commonJS({
4602
4602
  return cb(null, destStat);
4603
4603
  });
4604
4604
  }
4605
- module2.exports = copy4;
4605
+ module2.exports = copy3;
4606
4606
  }
4607
4607
  });
4608
4608
 
@@ -5274,7 +5274,7 @@ var require_jsonfile = __commonJS({
5274
5274
  } catch (_2) {
5275
5275
  _fs = require("fs");
5276
5276
  }
5277
- function readFile4(file, options, callback) {
5277
+ function readFile3(file, options, callback) {
5278
5278
  if (callback == null) {
5279
5279
  callback = options;
5280
5280
  options = {};
@@ -5373,7 +5373,7 @@ var require_jsonfile = __commonJS({
5373
5373
  return content;
5374
5374
  }
5375
5375
  var jsonfile = {
5376
- readFile: readFile4,
5376
+ readFile: readFile3,
5377
5377
  readFileSync,
5378
5378
  writeFile: writeFile2,
5379
5379
  writeFileSync
@@ -5573,7 +5573,7 @@ var require_move = __commonJS({
5573
5573
  var u2 = require_universalify().fromCallback;
5574
5574
  var fs3 = require_graceful_fs();
5575
5575
  var path = require("path");
5576
- var copy4 = require_copy2().copy;
5576
+ var copy3 = require_copy2().copy;
5577
5577
  var remove3 = require_remove().remove;
5578
5578
  var mkdirp3 = require_mkdirs2().mkdirp;
5579
5579
  var pathExists5 = require_path_exists().pathExists;
@@ -5630,7 +5630,7 @@ var require_move = __commonJS({
5630
5630
  overwrite,
5631
5631
  errorOnExist: true
5632
5632
  };
5633
- copy4(src, dest, opts, (err) => {
5633
+ copy3(src, dest, opts, (err) => {
5634
5634
  if (err)
5635
5635
  return cb(err);
5636
5636
  return remove3(src, cb);
@@ -7498,9 +7498,9 @@ var require_public_api = __commonJS({
7498
7498
  }
7499
7499
  });
7500
7500
 
7501
- // ../../node_modules/.pnpm/node-fetch@2.6.7/node_modules/node-fetch/lib/index.js
7501
+ // ../../node_modules/.pnpm/node-fetch@2.6.9/node_modules/node-fetch/lib/index.js
7502
7502
  var require_lib4 = __commonJS({
7503
- "../../node_modules/.pnpm/node-fetch@2.6.7/node_modules/node-fetch/lib/index.js"(exports, module2) {
7503
+ "../../node_modules/.pnpm/node-fetch@2.6.9/node_modules/node-fetch/lib/index.js"(exports, module2) {
7504
7504
  "use strict";
7505
7505
  Object.defineProperty(exports, "__esModule", { value: true });
7506
7506
  function _interopDefault(ex) {
@@ -8495,6 +8495,11 @@ var require_lib4 = __commonJS({
8495
8495
  const dest = new URL$1(destination).hostname;
8496
8496
  return orig === dest || orig[orig.length - dest.length - 1] === "." && orig.endsWith(dest);
8497
8497
  };
8498
+ var isSameProtocol = function isSameProtocol2(destination, original) {
8499
+ const orig = new URL$1(original).protocol;
8500
+ const dest = new URL$1(destination).protocol;
8501
+ return orig === dest;
8502
+ };
8498
8503
  function fetch(url, opts) {
8499
8504
  if (!fetch.Promise) {
8500
8505
  throw new Error("native promise missing, set fetch.Promise to your favorite alternative");
@@ -8510,7 +8515,7 @@ var require_lib4 = __commonJS({
8510
8515
  let error = new AbortError("The user aborted a request.");
8511
8516
  reject(error);
8512
8517
  if (request.body && request.body instanceof Stream.Readable) {
8513
- request.body.destroy(error);
8518
+ destroyStream(request.body, error);
8514
8519
  }
8515
8520
  if (!response || !response.body)
8516
8521
  return;
@@ -8545,8 +8550,31 @@ var require_lib4 = __commonJS({
8545
8550
  }
8546
8551
  req.on("error", function(err) {
8547
8552
  reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, "system", err));
8553
+ if (response && response.body) {
8554
+ destroyStream(response.body, err);
8555
+ }
8548
8556
  finalize();
8549
8557
  });
8558
+ fixResponseChunkedTransferBadEnding(req, function(err) {
8559
+ if (signal && signal.aborted) {
8560
+ return;
8561
+ }
8562
+ if (response && response.body) {
8563
+ destroyStream(response.body, err);
8564
+ }
8565
+ });
8566
+ if (parseInt(process.version.substring(1)) < 14) {
8567
+ req.on("socket", function(s3) {
8568
+ s3.addListener("close", function(hadError) {
8569
+ const hasDataListener = s3.listenerCount("data") > 0;
8570
+ if (response && hasDataListener && !hadError && !(signal && signal.aborted)) {
8571
+ const err = new Error("Premature close");
8572
+ err.code = "ERR_STREAM_PREMATURE_CLOSE";
8573
+ response.body.emit("error", err);
8574
+ }
8575
+ });
8576
+ });
8577
+ }
8550
8578
  req.on("response", function(res) {
8551
8579
  clearTimeout(reqTimeout);
8552
8580
  const headers = createHeadersLenient(res.headers);
@@ -8597,7 +8625,7 @@ var require_lib4 = __commonJS({
8597
8625
  timeout: request.timeout,
8598
8626
  size: request.size
8599
8627
  };
8600
- if (!isDomainOrSubdomain(request.url, locationURL)) {
8628
+ if (!isDomainOrSubdomain(request.url, locationURL) || !isSameProtocol(request.url, locationURL)) {
8601
8629
  for (const name of ["authorization", "www-authenticate", "cookie", "cookie2"]) {
8602
8630
  requestOpts.headers.delete(name);
8603
8631
  }
@@ -8658,6 +8686,12 @@ var require_lib4 = __commonJS({
8658
8686
  response = new Response(body, response_options);
8659
8687
  resolve(response);
8660
8688
  });
8689
+ raw.on("end", function() {
8690
+ if (!response) {
8691
+ response = new Response(body, response_options);
8692
+ resolve(response);
8693
+ }
8694
+ });
8661
8695
  return;
8662
8696
  }
8663
8697
  if (codings == "br" && typeof zlib.createBrotliDecompress === "function") {
@@ -8672,6 +8706,33 @@ var require_lib4 = __commonJS({
8672
8706
  writeToStream(req, request);
8673
8707
  });
8674
8708
  }
8709
+ function fixResponseChunkedTransferBadEnding(request, errorCallback) {
8710
+ let socket;
8711
+ request.on("socket", function(s3) {
8712
+ socket = s3;
8713
+ });
8714
+ request.on("response", function(response) {
8715
+ const headers = response.headers;
8716
+ if (headers["transfer-encoding"] === "chunked" && !headers["content-length"]) {
8717
+ response.once("close", function(hadError) {
8718
+ const hasDataListener = socket.listenerCount("data") > 0;
8719
+ if (hasDataListener && !hadError) {
8720
+ const err = new Error("Premature close");
8721
+ err.code = "ERR_STREAM_PREMATURE_CLOSE";
8722
+ errorCallback(err);
8723
+ }
8724
+ });
8725
+ }
8726
+ });
8727
+ }
8728
+ function destroyStream(stream, err) {
8729
+ if (stream.destroy) {
8730
+ stream.destroy(err);
8731
+ } else {
8732
+ stream.emit("error", err);
8733
+ stream.end();
8734
+ }
8735
+ }
8675
8736
  fetch.isRedirect = function(code) {
8676
8737
  return code === 301 || code === 302 || code === 303 || code === 307 || code === 308;
8677
8738
  };
@@ -10877,6 +10938,84 @@ var require_xdg_app_paths = __commonJS({
10877
10938
  }
10878
10939
  });
10879
10940
 
10941
+ // ../../internals/ipc-proxy/dist/index.js
10942
+ var require_dist2 = __commonJS({
10943
+ "../../internals/ipc-proxy/dist/index.js"(exports, module2) {
10944
+ "use strict";
10945
+ var __defProp2 = Object.defineProperty;
10946
+ var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
10947
+ var __getOwnPropNames2 = Object.getOwnPropertyNames;
10948
+ var __hasOwnProp2 = Object.prototype.hasOwnProperty;
10949
+ var __export2 = (target, all) => {
10950
+ for (var name in all)
10951
+ __defProp2(target, name, { get: all[name], enumerable: true });
10952
+ };
10953
+ var __copyProps2 = (to2, from, except, desc) => {
10954
+ if (from && typeof from === "object" || typeof from === "function") {
10955
+ for (let key of __getOwnPropNames2(from))
10956
+ if (!__hasOwnProp2.call(to2, key) && key !== except)
10957
+ __defProp2(to2, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
10958
+ }
10959
+ return to2;
10960
+ };
10961
+ var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
10962
+ var src_exports2 = {};
10963
+ __export2(src_exports2, {
10964
+ createStandaloneLambda: () => createStandaloneLambda2,
10965
+ getBootstrapDir: () => getBootstrapDir,
10966
+ getProxyBinaryPath: () => getProxyBinaryPath
10967
+ });
10968
+ module2.exports = __toCommonJS2(src_exports2);
10969
+ var import_node_path10 = require("path");
10970
+ var import_node_fs7 = require("fs");
10971
+ var import_promises2 = require("fs/promises");
10972
+ var import_build_utils6 = require("@vercel/build-utils");
10973
+ function proxyBinaryName(architecture) {
10974
+ return architecture === "arm64" ? "proxy-linux-arm64" : "proxy-linux-amd64";
10975
+ }
10976
+ function getProxyBinaryPath(architecture) {
10977
+ const binPath = (0, import_node_path10.join)(__dirname, "..", "bin", proxyBinaryName(architecture));
10978
+ if (!(0, import_node_fs7.existsSync)(binPath)) {
10979
+ throw new Error(
10980
+ `IPC proxy binary not found for architecture "${architecture}" at ${binPath}. Ensure @vercel-internals/ipc-proxy has been built and its prebuilt binaries copied alongside the consumer's dist output.`
10981
+ );
10982
+ }
10983
+ return binPath;
10984
+ }
10985
+ function getBootstrapDir() {
10986
+ return (0, import_node_path10.join)(__dirname, "..", "bootstrap");
10987
+ }
10988
+ async function createStandaloneLambda2(options) {
10989
+ const {
10990
+ userServerPath,
10991
+ architecture,
10992
+ lambdaOptions,
10993
+ includedFiles,
10994
+ runtimeLanguage,
10995
+ supportsResponseStreaming = true
10996
+ } = options;
10997
+ const proxyPath = getProxyBinaryPath(architecture);
10998
+ const [proxyData, userServerData] = await Promise.all([
10999
+ (0, import_promises2.readFile)(proxyPath),
11000
+ (0, import_promises2.readFile)(userServerPath)
11001
+ ]);
11002
+ return new import_build_utils6.Lambda({
11003
+ ...lambdaOptions,
11004
+ files: {
11005
+ ...includedFiles,
11006
+ executable: new import_build_utils6.FileBlob({ mode: 493, data: proxyData }),
11007
+ "user-server": new import_build_utils6.FileBlob({ mode: 493, data: userServerData })
11008
+ },
11009
+ handler: "executable",
11010
+ runtime: "executable",
11011
+ supportsResponseStreaming,
11012
+ architecture,
11013
+ runtimeLanguage
11014
+ });
11015
+ }
11016
+ }
11017
+ });
11018
+
10880
11019
  // src/index.ts
10881
11020
  var src_exports = {};
10882
11021
  __export(src_exports, {
@@ -10886,7 +11025,7 @@ __export(src_exports, {
10886
11025
  diagnostics: () => diagnostics,
10887
11026
  getNewHandlerFunctionName: () => getNewHandlerFunctionName,
10888
11027
  prepareCache: () => prepareCache,
10889
- shouldServe: () => import_build_utils5.shouldServe,
11028
+ shouldServe: () => shouldServe,
10890
11029
  startDevServer: () => startDevServer,
10891
11030
  version: () => version
10892
11031
  });
@@ -14665,9 +14804,11 @@ var detectEntrypoint = async ({ workPath }) => {
14665
14804
 
14666
14805
  // src/standalone-server.ts
14667
14806
  var import_child_process = require("child_process");
14807
+ var import_net = require("net");
14668
14808
  var import_path6 = require("path");
14669
14809
  var import_fs_extra3 = __toESM(require_lib2());
14670
14810
  var import_build_utils4 = require("@vercel/build-utils");
14811
+ var import_ipc_proxy = __toESM(require_dist2());
14671
14812
 
14672
14813
  // src/diagnostics.ts
14673
14814
  var import_build_utils3 = require("@vercel/build-utils");
@@ -14802,7 +14943,6 @@ async function buildStandaloneServer({
14802
14943
  });
14803
14944
  const outDir = await (0, import_build_utils4.getWriteableDirectory)();
14804
14945
  const userServerPath = (0, import_path6.join)(outDir, "user-server");
14805
- const bootstrapPath = (0, import_path6.join)(outDir, "executable");
14806
14946
  const vendorModulesPath = (0, import_path6.join)(workPath, "vendor", "modules.txt");
14807
14947
  const isVendored = await (0, import_fs_extra3.pathExists)(vendorModulesPath);
14808
14948
  if (isVendored) {
@@ -14829,35 +14969,6 @@ async function buildStandaloneServer({
14829
14969
  throw err;
14830
14970
  }
14831
14971
  }
14832
- const bootstrapDir = (0, import_path6.join)(__dirname, "../bootstrap");
14833
- const bootstrapSrc = (0, import_path6.join)(bootstrapDir, "vc-init.go");
14834
- const utilsSrc = (0, import_path6.join)(bootstrapDir, "vc-utils.go");
14835
- const bootstrapGoModSrc = (0, import_path6.join)(bootstrapDir, "go.mod");
14836
- (0, import_build_utils4.debug)(`Building bootstrap wrapper: ${bootstrapSrc} -> ${bootstrapPath}`);
14837
- try {
14838
- const bootstrapBuildDir = await (0, import_build_utils4.getWriteableDirectory)();
14839
- const bootstrapGoFile = (0, import_path6.join)(bootstrapBuildDir, "main.go");
14840
- await (0, import_fs_extra3.copy)(bootstrapSrc, bootstrapGoFile);
14841
- await (0, import_fs_extra3.copy)(utilsSrc, (0, import_path6.join)(bootstrapBuildDir, "vc-utils.go"));
14842
- await (0, import_fs_extra3.copy)(bootstrapGoModSrc, (0, import_path6.join)(bootstrapBuildDir, "go.mod"));
14843
- const bootstrapEnv = {
14844
- PATH: process.env.PATH || "",
14845
- HOME: process.env.HOME || "",
14846
- TMPDIR: process.env.TMPDIR || "",
14847
- GOARCH: architecture === "arm64" ? "arm64" : "amd64",
14848
- GOOS: "linux",
14849
- CGO_ENABLED: "0"
14850
- };
14851
- const bootstrapGo = await createGo({
14852
- modulePath: bootstrapBuildDir,
14853
- opts: { cwd: bootstrapBuildDir, env: bootstrapEnv },
14854
- workPath: bootstrapBuildDir
14855
- });
14856
- await bootstrapGo.build(".", bootstrapPath);
14857
- } catch (err) {
14858
- console.error("Failed to build bootstrap wrapper");
14859
- throw err;
14860
- }
14861
14972
  const includedFiles = {};
14862
14973
  if (config && config.includeFiles) {
14863
14974
  const patterns = Array.isArray(config.includeFiles) ? config.includeFiles : [config.includeFiles];
@@ -14868,24 +14979,13 @@ async function buildStandaloneServer({
14868
14979
  }
14869
14980
  }
14870
14981
  }
14871
- const [userServerData, bootstrapData] = await Promise.all([
14872
- (0, import_fs_extra3.readFile)(userServerPath),
14873
- (0, import_fs_extra3.readFile)(bootstrapPath)
14874
- ]);
14875
- const lambda = new import_build_utils4.Lambda({
14876
- ...lambdaOptions,
14877
- files: {
14878
- ...includedFiles,
14879
- // Bootstrap is the main entrypoint (handles IPC protocol)
14880
- executable: new import_build_utils4.FileBlob({ mode: 493, data: bootstrapData }),
14881
- // User's server is spawned by bootstrap
14882
- "user-server": new import_build_utils4.FileBlob({ mode: 493, data: userServerData })
14883
- },
14884
- handler: "executable",
14885
- runtime: "executable",
14886
- supportsResponseStreaming: true,
14982
+ const lambda = await (0, import_ipc_proxy.createStandaloneLambda)({
14983
+ userServerPath,
14887
14984
  architecture,
14888
- runtimeLanguage: "go"
14985
+ lambdaOptions,
14986
+ includedFiles,
14987
+ runtimeLanguage: "go",
14988
+ supportsResponseStreaming: true
14889
14989
  });
14890
14990
  const preDeployCommand = config?.preDeployCommand;
14891
14991
  if (registerPreDeploy && typeof preDeployCommand === "string") {
@@ -14909,69 +15009,194 @@ async function buildStandaloneServer({
14909
15009
  });
14910
15010
  return { output: lambda };
14911
15011
  }
14912
- async function startStandaloneDevServer(opts, resolvedEntrypoint) {
14913
- const { workPath, meta = {} } = opts;
14914
- const port = Math.floor(Math.random() * (65535 - 49152) + 49152);
14915
- const env = (0, import_build_utils4.cloneEnv)(process.env, meta.env, {
14916
- PORT: String(port)
14917
- });
14918
- const runTarget = resolvedEntrypoint === "main.go" ? "." : "./" + (0, import_path6.dirname)(resolvedEntrypoint);
14919
- const devWrapper = (0, import_path6.join)(__dirname, "../bootstrap/vc-init-dev.go");
14920
- const devUtils = (0, import_path6.join)(__dirname, "../bootstrap/vc-utils.go");
14921
- (0, import_build_utils4.debug)(
14922
- `Starting standalone Go dev server wrapper: go run ${devWrapper} (target ${runTarget}, port ${port})`
14923
- );
14924
- const child = (0, import_child_process.spawn)("go", ["run", "-tags", "vcdev", devWrapper, devUtils], {
14925
- cwd: workPath,
14926
- env: {
14927
- ...env,
14928
- __VC_GO_DEV_RUN_TARGET: runTarget
14929
- },
14930
- stdio: ["ignore", "pipe", "pipe"]
14931
- });
14932
- child.stdout?.on("data", (data) => {
14933
- const chunk = Buffer.isBuffer(data) ? data : Buffer.from(data);
14934
- if (opts.onStdout) {
14935
- opts.onStdout(chunk);
15012
+ var DEV_SERVER_STARTUP_TIMEOUT = 5 * 6e4;
15013
+ var PERSISTENT_SERVERS = /* @__PURE__ */ new Map();
15014
+ var PENDING_STARTS = /* @__PURE__ */ new Map();
15015
+ var cleanupHandlersInstalled = false;
15016
+ function killStandaloneDevServer(pid) {
15017
+ try {
15018
+ if (process.platform === "win32") {
15019
+ process.kill(pid, "SIGTERM");
14936
15020
  } else {
14937
- process.stdout.write(chunk.toString());
15021
+ process.kill(-pid, "SIGTERM");
14938
15022
  }
14939
- });
14940
- child.stderr?.on("data", (data) => {
14941
- const chunk = Buffer.isBuffer(data) ? data : Buffer.from(data);
14942
- if (opts.onStderr) {
14943
- opts.onStderr(chunk);
14944
- } else {
14945
- process.stderr.write(chunk.toString());
15023
+ } catch (err) {
15024
+ (0, import_build_utils4.debug)(`Error killing standalone Go dev server ${pid}: ${err}`);
15025
+ }
15026
+ }
15027
+ function installGlobalCleanupHandlers() {
15028
+ if (cleanupHandlersInstalled)
15029
+ return;
15030
+ cleanupHandlersInstalled = true;
15031
+ const killAll = () => {
15032
+ for (const [key, info] of PERSISTENT_SERVERS.entries()) {
15033
+ killStandaloneDevServer(info.pid);
15034
+ PERSISTENT_SERVERS.delete(key);
14946
15035
  }
15036
+ };
15037
+ process.on("SIGINT", () => {
15038
+ killAll();
14947
15039
  });
14948
- await new Promise((resolve, reject) => {
14949
- const timeout = setTimeout(() => {
14950
- cleanup();
14951
- resolve();
14952
- }, 2e3);
14953
- const onExit = (code, signal) => {
14954
- cleanup();
14955
- reject(
14956
- new Error(
14957
- `Standalone Go dev server exited before startup completed (code: ${code}, signal: ${signal})`
14958
- )
14959
- );
14960
- };
14961
- const cleanup = () => {
14962
- clearTimeout(timeout);
14963
- child.removeListener("exit", onExit);
14964
- };
14965
- child.once("exit", onExit);
15040
+ process.on("SIGTERM", () => {
15041
+ killAll();
14966
15042
  });
14967
- return {
14968
- port,
14969
- pid: child.pid
15043
+ process.on("exit", () => {
15044
+ killAll();
15045
+ });
15046
+ }
15047
+ function isPortReachable(port) {
15048
+ return new Promise((resolve) => {
15049
+ const socket = (0, import_net.createConnection)({ port, host: "127.0.0.1" });
15050
+ const done = (result) => {
15051
+ socket.removeAllListeners();
15052
+ socket.destroy();
15053
+ resolve(result);
15054
+ };
15055
+ socket.setTimeout(1e3);
15056
+ socket.once("connect", () => done(true));
15057
+ socket.once("timeout", () => done(false));
15058
+ socket.once("error", () => done(false));
15059
+ });
15060
+ }
15061
+ function sleep(ms2) {
15062
+ return new Promise((resolve) => setTimeout(resolve, ms2));
15063
+ }
15064
+ async function waitForPort(port, child, timeout) {
15065
+ let exited = null;
15066
+ let spawnError = null;
15067
+ const onExit = (code, signal) => {
15068
+ exited = { code, signal };
15069
+ };
15070
+ const onError = (err) => {
15071
+ spawnError = err;
14970
15072
  };
15073
+ child.once("exit", onExit);
15074
+ child.once("error", onError);
15075
+ try {
15076
+ const start = Date.now();
15077
+ while (Date.now() - start < timeout) {
15078
+ if (spawnError) {
15079
+ throw spawnError;
15080
+ }
15081
+ if (exited) {
15082
+ const { code, signal } = exited;
15083
+ throw new Error(
15084
+ `Standalone Go dev server exited before startup completed (code: ${code}, signal: ${signal})`
15085
+ );
15086
+ }
15087
+ if (await isPortReachable(port)) {
15088
+ return;
15089
+ }
15090
+ await sleep(100);
15091
+ }
15092
+ throw new Error(
15093
+ `Standalone Go dev server did not start within ${timeout}ms`
15094
+ );
15095
+ } finally {
15096
+ child.removeListener("exit", onExit);
15097
+ child.removeListener("error", onError);
15098
+ }
15099
+ }
15100
+ async function startStandaloneDevServer(opts, resolvedEntrypoint) {
15101
+ const { workPath, meta = {} } = opts;
15102
+ const serverKey = `${workPath}::${resolvedEntrypoint}`;
15103
+ const existing = PERSISTENT_SERVERS.get(serverKey);
15104
+ if (existing) {
15105
+ return {
15106
+ port: existing.port,
15107
+ pid: existing.pid,
15108
+ shutdown: async () => {
15109
+ }
15110
+ };
15111
+ }
15112
+ const pending = PENDING_STARTS.get(serverKey);
15113
+ if (pending) {
15114
+ const { port, pid } = await pending;
15115
+ return { port, pid, shutdown: async () => {
15116
+ } };
15117
+ }
15118
+ const startPromise = (async () => {
15119
+ const port = Math.floor(Math.random() * (65535 - 49152) + 49152);
15120
+ const env = (0, import_build_utils4.cloneEnv)(process.env, meta.env, {
15121
+ PORT: String(port)
15122
+ });
15123
+ const entrypointDir = (0, import_path6.dirname)((0, import_path6.join)(workPath, resolvedEntrypoint));
15124
+ const { goModPath } = await findGoModPath(entrypointDir, workPath);
15125
+ const modulePath = goModPath ? (0, import_path6.dirname)(goModPath) : workPath;
15126
+ const go = await createGo({
15127
+ modulePath,
15128
+ opts: { cwd: workPath, env },
15129
+ workPath
15130
+ });
15131
+ const runTarget = resolvedEntrypoint === "main.go" ? "." : "./" + (0, import_path6.dirname)(resolvedEntrypoint);
15132
+ const devWrapper = (0, import_path6.join)(__dirname, "../bootstrap/vc-init-dev.go");
15133
+ const devUtils = (0, import_path6.join)(__dirname, "../bootstrap/utils.go");
15134
+ (0, import_build_utils4.debug)(
15135
+ `Starting standalone Go dev server wrapper: go run ${devWrapper} (target ${runTarget}, port ${port})`
15136
+ );
15137
+ const child = (0, import_child_process.spawn)("go", ["run", "-tags", "vcdev", devWrapper, devUtils], {
15138
+ cwd: workPath,
15139
+ env: {
15140
+ ...go.getEnv(),
15141
+ __VC_GO_DEV_RUN_TARGET: runTarget
15142
+ },
15143
+ stdio: ["ignore", "pipe", "pipe"],
15144
+ detached: process.platform !== "win32"
15145
+ });
15146
+ child.stdout?.on("data", (data) => {
15147
+ const chunk = Buffer.isBuffer(data) ? data : Buffer.from(data);
15148
+ if (opts.onStdout) {
15149
+ opts.onStdout(chunk);
15150
+ } else {
15151
+ process.stdout.write(chunk.toString());
15152
+ }
15153
+ });
15154
+ child.stderr?.on("data", (data) => {
15155
+ const chunk = Buffer.isBuffer(data) ? data : Buffer.from(data);
15156
+ if (opts.onStderr) {
15157
+ opts.onStderr(chunk);
15158
+ } else {
15159
+ process.stderr.write(chunk.toString());
15160
+ }
15161
+ });
15162
+ const pid = child.pid;
15163
+ try {
15164
+ await waitForPort(port, child, DEV_SERVER_STARTUP_TIMEOUT);
15165
+ } catch (err) {
15166
+ if (pid) {
15167
+ killStandaloneDevServer(pid);
15168
+ }
15169
+ throw err;
15170
+ }
15171
+ if (!pid) {
15172
+ throw new Error("Standalone Go dev server started without a PID");
15173
+ }
15174
+ PERSISTENT_SERVERS.set(serverKey, { port, pid, child });
15175
+ child.once("exit", () => {
15176
+ PERSISTENT_SERVERS.delete(serverKey);
15177
+ });
15178
+ installGlobalCleanupHandlers();
15179
+ return { port, pid };
15180
+ })();
15181
+ PENDING_STARTS.set(serverKey, startPromise);
15182
+ try {
15183
+ const { port, pid } = await startPromise;
15184
+ return { port, pid, shutdown: async () => {
15185
+ } };
15186
+ } finally {
15187
+ PENDING_STARTS.delete(serverKey);
15188
+ }
14971
15189
  }
14972
15190
 
14973
15191
  // src/index.ts
14974
15192
  var TMP = (0, import_os2.tmpdir)();
15193
+ var shouldServe = (opts) => {
15194
+ const framework = opts.config.framework;
15195
+ if (framework === "go" || framework === "services") {
15196
+ return true;
15197
+ }
15198
+ return (0, import_build_utils5.shouldServe)(opts);
15199
+ };
14975
15200
  var MAIN_GO_FILENAME = "main__vc__go__.go";
14976
15201
  var HANDLER_FILENAME = `bootstrap${OUT_EXTENSION}`;
14977
15202
  async function initPrivateGit(credentials) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/go",
3
- "version": "3.8.0",
3
+ "version": "3.9.1",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index",
6
6
  "homepage": "https://vercel.com/docs/runtimes#official-runtimes/go",
@@ -12,6 +12,7 @@
12
12
  "files": [
13
13
  "dist",
14
14
  "*.go",
15
+ "bin",
15
16
  "bootstrap"
16
17
  ],
17
18
  "devDependencies": {
@@ -31,10 +32,11 @@
31
32
  "vitest": "2.0.3",
32
33
  "xdg-app-paths": "5.1.0",
33
34
  "yauzl-promise": "2.1.3",
34
- "@vercel/build-utils": "13.26.2"
35
+ "@vercel-internals/ipc-proxy": "1.0.0",
36
+ "@vercel/build-utils": "13.30.0"
35
37
  },
36
38
  "scripts": {
37
- "build": "node ../../utils/build-builder.mjs",
39
+ "build": "node build.mjs",
38
40
  "test": "vitest run --config ../../vitest.config.mts",
39
41
  "test-e2e": "pnpm test test/integration-*",
40
42
  "type-check": "tsc --noEmit",
package/bootstrap/go.mod DELETED
@@ -1,3 +0,0 @@
1
- module vc-init
2
-
3
- go 1.23
@@ -1,274 +0,0 @@
1
- // vc-init.go - Bootstrap wrapper for standalone Go servers on Vercel
2
- // This handles the IPC protocol required for executable runtime mode.
3
- //
4
- // The bootstrap:
5
- // 1. Connects to VERCEL_IPC_PATH Unix socket
6
- // 2. Starts the user's server on an internal port
7
- // 3. Sends "server-started" IPC message
8
- // 4. Reverse proxies requests to user's server
9
- // 5. Handles /_vercel/ping health check
10
- // 6. Sends "end" IPC message after each request
11
-
12
- package main
13
-
14
- import (
15
- "context"
16
- "encoding/json"
17
- "errors"
18
- "fmt"
19
- "net"
20
- "net/http"
21
- "net/http/httputil"
22
- "net/url"
23
- "os"
24
- "os/exec"
25
- "strconv"
26
- "strings"
27
- "sync"
28
- "time"
29
- )
30
-
31
- // IPC message types
32
- type StartMessage struct {
33
- Type string `json:"type"`
34
- Payload StartPayload `json:"payload"`
35
- }
36
-
37
- type StartPayload struct {
38
- InitDuration int `json:"initDuration"`
39
- HTTPPort int `json:"httpPort"`
40
- }
41
-
42
- type EndMessage struct {
43
- Type string `json:"type"`
44
- Payload EndPayload `json:"payload"`
45
- }
46
-
47
- type EndPayload struct {
48
- Context RequestContext `json:"context"`
49
- Error interface{} `json:"error,omitempty"`
50
- }
51
-
52
- type RequestContext struct {
53
- InvocationID string `json:"invocationId"`
54
- RequestID uint64 `json:"requestId"`
55
- }
56
-
57
- type UnrecoverableErrorMessage struct {
58
- Type string `json:"type"`
59
- Payload UnrecoverableErrorPayload `json:"payload"`
60
- }
61
-
62
- type UnrecoverableErrorPayload struct {
63
- ExitCode int `json:"exitCode"`
64
- Message string `json:"message"`
65
- }
66
-
67
- var (
68
- ipcConn net.Conn
69
- ipcMutex sync.Mutex
70
- ipcReady bool
71
- startTime time.Time
72
- )
73
-
74
- func sendIPCMessage(msg interface{}) error {
75
- if ipcConn == nil {
76
- return nil
77
- }
78
-
79
- ipcMutex.Lock()
80
- defer ipcMutex.Unlock()
81
-
82
- data, err := json.Marshal(msg)
83
- if err != nil {
84
- return err
85
- }
86
-
87
- // IPC messages are JSON followed by null byte
88
- _, err = ipcConn.Write(append(data, 0))
89
- return err
90
- }
91
-
92
- // fatal reports a fatal init error via IPC and exits.
93
- func fatal(exitCode int, msg string) {
94
- fmt.Fprintln(os.Stderr, msg)
95
- sendIPCMessage(UnrecoverableErrorMessage{
96
- Type: "unrecoverable-error",
97
- Payload: UnrecoverableErrorPayload{
98
- ExitCode: exitCode,
99
- Message: msg,
100
- },
101
- })
102
- os.Exit(exitCode)
103
- }
104
-
105
- func connectIPC() error {
106
- ipcPath := os.Getenv("VERCEL_IPC_PATH")
107
- if ipcPath == "" {
108
- // No IPC path - running in dev mode or locally
109
- return nil
110
- }
111
-
112
- conn, err := net.Dial("unix", ipcPath)
113
- if err != nil {
114
- return fmt.Errorf("failed to connect to IPC socket: %w", err)
115
- }
116
-
117
- ipcConn = conn
118
- return nil
119
- }
120
-
121
- func main() {
122
- startTime = time.Now()
123
- serviceRoutePrefix := resolveServiceRoutePrefix()
124
-
125
- // Connect to IPC socket
126
- if err := connectIPC(); err != nil {
127
- fmt.Fprintf(os.Stderr, "Warning: %v\n", err)
128
- }
129
-
130
- // Find a free port for the user's server
131
- userPort, err := findFreePort()
132
- if err != nil {
133
- fatal(1, fmt.Sprintf("Failed to find free port: %v", err))
134
- }
135
-
136
- // Start the user's server binary
137
- userBinary := "./user-server"
138
- if _, err := os.Stat(userBinary); os.IsNotExist(err) {
139
- fatal(1, fmt.Sprintf("User server binary not found: %s", userBinary))
140
- }
141
-
142
- ctx, cancel := context.WithCancel(context.Background())
143
- defer cancel()
144
-
145
- cmd := exec.CommandContext(ctx, userBinary)
146
- cmd.Env = append(os.Environ(), fmt.Sprintf("PORT=%d", userPort))
147
- cmd.Stdout = os.Stdout
148
- cmd.Stderr = os.Stderr
149
-
150
- if err := cmd.Start(); err != nil {
151
- fatal(1, fmt.Sprintf("Failed to start user server: %v", err))
152
- }
153
-
154
- // Race server readiness against early child death.
155
- childDone := make(chan error, 1)
156
- go func() { childDone <- cmd.Wait() }()
157
-
158
- serverReady := make(chan error, 1)
159
- go func() { serverReady <- waitForServer(userPort, 30*time.Second) }()
160
-
161
- select {
162
- case waitErr := <-childDone:
163
- // Child exited before the server became ready.
164
- exitCode := 1
165
- var exitErr *exec.ExitError
166
- if errors.As(waitErr, &exitErr) {
167
- exitCode = exitErr.ExitCode()
168
- }
169
- fatal(exitCode, "User server exited during startup")
170
- case err := <-serverReady:
171
- if err != nil {
172
- cmd.Process.Kill()
173
- fatal(1, fmt.Sprintf("User server failed to start: %v", err))
174
- }
175
- }
176
-
177
- // Create reverse proxy to user's server
178
- targetURL, _ := url.Parse(fmt.Sprintf("http://127.0.0.1:%d", userPort))
179
- proxy := httputil.NewSingleHostReverseProxy(targetURL)
180
-
181
- // Customize the proxy director to preserve headers
182
- originalDirector := proxy.Director
183
- proxy.Director = func(req *http.Request) {
184
- originalDirector(req)
185
- // Preserve the original Host header
186
- if host := req.Header.Get("X-Forwarded-Host"); host != "" {
187
- req.Host = host
188
- }
189
- }
190
-
191
- // The port we'll listen on (Vercel will route traffic here)
192
- listenPort := 3000
193
-
194
- // Create HTTP server with IPC-aware handler
195
- server := &http.Server{
196
- Addr: fmt.Sprintf("127.0.0.1:%d", listenPort),
197
- Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
198
- // Handle Vercel health check
199
- if r.URL.Path == "/_vercel/ping" {
200
- w.WriteHeader(http.StatusOK)
201
- w.Write([]byte("OK"))
202
- return
203
- }
204
-
205
- // Extract Vercel internal headers
206
- invocationID := r.Header.Get("X-Vercel-Internal-Invocation-Id")
207
- requestIDStr := r.Header.Get("X-Vercel-Internal-Request-Id")
208
- requestID, _ := strconv.ParseUint(requestIDStr, 10, 64)
209
-
210
- // Remove internal headers before forwarding
211
- for key := range r.Header {
212
- if strings.HasPrefix(strings.ToLower(key), "x-vercel-internal-") {
213
- r.Header.Del(key)
214
- }
215
- }
216
-
217
- if r.URL != nil {
218
- originalPath := r.URL.Path
219
- r.URL.Path = stripServiceRoutePrefix(r.URL.Path, serviceRoutePrefix)
220
- if r.URL.Path != originalPath {
221
- // Keep URL path encoding fields consistent after rewrite.
222
- r.URL.RawPath = ""
223
- }
224
- }
225
-
226
- // Forward request to user's server
227
- proxy.ServeHTTP(w, r)
228
-
229
- // Send end message via IPC
230
- if ipcConn != nil && invocationID != "" {
231
- endMsg := EndMessage{
232
- Type: "end",
233
- Payload: EndPayload{
234
- Context: RequestContext{
235
- InvocationID: invocationID,
236
- RequestID: requestID,
237
- },
238
- },
239
- }
240
- sendIPCMessage(endMsg)
241
- }
242
- }),
243
- }
244
-
245
- // Send server-started IPC message
246
- initDuration := int(time.Since(startTime).Milliseconds())
247
- startMsg := StartMessage{
248
- Type: "server-started",
249
- Payload: StartPayload{
250
- InitDuration: initDuration,
251
- HTTPPort: listenPort,
252
- },
253
- }
254
-
255
- if err := sendIPCMessage(startMsg); err != nil {
256
- fmt.Fprintf(os.Stderr, "Warning: Failed to send IPC start message: %v\n", err)
257
- } else {
258
- ipcReady = true
259
- }
260
-
261
- // If no IPC, print the port for local development
262
- if ipcConn == nil {
263
- fmt.Printf("Server listening on port %d (proxying to user server on port %d)\n", listenPort, userPort)
264
- }
265
-
266
- // Start the proxy server
267
- if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
268
- fmt.Fprintf(os.Stderr, "Server error: %v\n", err)
269
- os.Exit(1)
270
- }
271
-
272
- // Clean up
273
- cmd.Process.Kill()
274
- }
File without changes