@patchstack/connect 0.2.10 → 0.2.11

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/dist/cli.js CHANGED
@@ -1108,6 +1108,94 @@ function isEnvironment(value) {
1108
1108
  // src/mark-build.ts
1109
1109
  import { existsSync, readdirSync, statSync } from "fs";
1110
1110
  import path7 from "path";
1111
+
1112
+ // src/stack.ts
1113
+ var STACK_RULES = [
1114
+ // Meta-frameworks (most specific first).
1115
+ { category: "framework", pkg: "@tanstack/react-start", label: "tanstack-start" },
1116
+ { category: "framework", pkg: "@tanstack/start", label: "tanstack-start" },
1117
+ { category: "framework", pkg: "next", label: "next" },
1118
+ { category: "framework", pkg: "nuxt", label: "nuxt" },
1119
+ { category: "framework", pkg: "@remix-run/react", label: "remix" },
1120
+ { category: "framework", pkg: "@remix-run/node", label: "remix" },
1121
+ { category: "framework", pkg: "react-router", label: "react-router" },
1122
+ { category: "framework", pkg: "astro", label: "astro" },
1123
+ { category: "framework", pkg: "@sveltejs/kit", label: "sveltekit" },
1124
+ { category: "framework", pkg: "@builder.io/qwik-city", label: "qwik-city" },
1125
+ { category: "framework", pkg: "gatsby", label: "gatsby" },
1126
+ { category: "framework", pkg: "express", label: "express" },
1127
+ { category: "framework", pkg: "fastify", label: "fastify" },
1128
+ // UI runtimes.
1129
+ { category: "ui", pkg: "@angular/core", label: "angular" },
1130
+ { category: "ui", pkg: "react-dom", label: "react" },
1131
+ { category: "ui", pkg: "react", label: "react" },
1132
+ { category: "ui", pkg: "vue", label: "vue" },
1133
+ { category: "ui", pkg: "svelte", label: "svelte" },
1134
+ { category: "ui", pkg: "solid-js", label: "solid" },
1135
+ { category: "ui", pkg: "preact", label: "preact" },
1136
+ // Bundlers / build tools.
1137
+ { category: "bundler", pkg: "vite", label: "vite" },
1138
+ { category: "bundler", pkg: "@rspack/core", label: "rspack" },
1139
+ { category: "bundler", pkg: "webpack", label: "webpack" },
1140
+ { category: "bundler", pkg: "parcel", label: "parcel" },
1141
+ { category: "bundler", pkg: "rollup", label: "rollup" },
1142
+ { category: "bundler", pkg: "esbuild", label: "esbuild" },
1143
+ // Deployment-runtime hints from build deps.
1144
+ { category: "runtime", pkg: "wrangler", label: "cloudflare-workers" },
1145
+ { category: "runtime", pkg: "@cloudflare/workers-types", label: "cloudflare-workers" },
1146
+ { category: "runtime", pkg: "@cloudflare/vite-plugin", label: "cloudflare-workers" },
1147
+ { category: "runtime", pkg: "@vercel/node", label: "vercel" },
1148
+ { category: "runtime", pkg: "@netlify/functions", label: "netlify" },
1149
+ { category: "runtime", pkg: "@netlify/blobs", label: "netlify" },
1150
+ // Vibe / builder platforms — the "learn from each platform" signal.
1151
+ { category: "builder", pkg: "lovable-tagger", label: "lovable" },
1152
+ { category: "builder", pkg: "@replit/vite-plugin-runtime-error-modal", label: "replit" },
1153
+ { category: "builder", pkg: "@replit/vite-plugin-cartographer", label: "replit" }
1154
+ ];
1155
+ var HOSTING_ENV_PATTERNS = [
1156
+ /^CF_/,
1157
+ /^CLOUDFLARE_/,
1158
+ /^VERCEL/,
1159
+ /^NETLIFY/,
1160
+ /^AWS_(LAMBDA|REGION|EXECUTION)/,
1161
+ /^FLY_/,
1162
+ /^RENDER/,
1163
+ /^RAILWAY_/,
1164
+ /^DENO_/,
1165
+ /^EDGE_RUNTIME/,
1166
+ /^DYNO$/,
1167
+ /^K_SERVICE$/,
1168
+ /^GAE_/,
1169
+ /^FUNCTION_/
1170
+ ];
1171
+ function collectHostingEnvKeys(env = process.env) {
1172
+ return Object.keys(env).filter((key) => HOSTING_ENV_PATTERNS.some((pattern) => pattern.test(key))).sort();
1173
+ }
1174
+ function detectStack(packages, env = process.env) {
1175
+ const present = new Set(packages.map((pkg) => pkg.name));
1176
+ const firstMatch = (category) => {
1177
+ for (const rule of STACK_RULES) {
1178
+ if (rule.category === category && present.has(rule.pkg)) {
1179
+ return rule.label;
1180
+ }
1181
+ }
1182
+ return null;
1183
+ };
1184
+ return {
1185
+ framework: firstMatch("framework"),
1186
+ ui: firstMatch("ui"),
1187
+ bundler: firstMatch("bundler"),
1188
+ runtime: firstMatch("runtime"),
1189
+ builder: firstMatch("builder"),
1190
+ ecosystem: "npm",
1191
+ hostingEnvKeys: collectHostingEnvKeys(env)
1192
+ };
1193
+ }
1194
+ function isEmptyStack(stack) {
1195
+ return stack.framework === null && stack.ui === null && stack.bundler === null && stack.runtime === null && stack.builder === null && stack.hostingEnvKeys.length === 0;
1196
+ }
1197
+
1198
+ // src/mark-build.ts
1111
1199
  var MARKER_ATTR = "data-patchstack-build";
1112
1200
  var BUILD_DIR_CANDIDATES = ["dist", "build", "out", ".output/public"];
1113
1201
  function resolveBuildDir(cwd, override) {
@@ -1138,11 +1226,14 @@ function findHtmlFiles(dir) {
1138
1226
  walk2(dir);
1139
1227
  return out;
1140
1228
  }
1141
- function buildInjectionSnippet(checksum) {
1229
+ function buildInjectionSnippet(checksum, stack) {
1142
1230
  const statements = ["window.__PATCHSTACK_PROD__=true;"];
1143
1231
  if (checksum !== null && checksum !== "") {
1144
1232
  statements.push(`window.__PATCHSTACK_BUILD__=${JSON.stringify(checksum)};`);
1145
1233
  }
1234
+ if (stack != null && !isEmptyStack(stack)) {
1235
+ statements.push(`window.__PATCHSTACK_STACK__=${JSON.stringify(stack)};`);
1236
+ }
1146
1237
  return `<script ${MARKER_ATTR}>${statements.join("")}</script>`;
1147
1238
  }
1148
1239
  function injectMarker(html, snippet) {
@@ -1479,9 +1570,19 @@ async function runStatus(args) {
1479
1570
  }
1480
1571
  return 0;
1481
1572
  }
1573
+ function describeStack(stack) {
1574
+ const parts = [stack.builder, stack.framework, stack.ui, stack.runtime].filter(
1575
+ (part) => part !== null
1576
+ );
1577
+ if (stack.hostingEnvKeys.length > 0) {
1578
+ parts.push(`${stack.hostingEnvKeys.length} hosting env key(s)`);
1579
+ }
1580
+ return parts.length > 0 ? parts.join(" \xB7 ") : null;
1581
+ }
1482
1582
  async function runMarkBuild(args) {
1483
1583
  const cwd = process.cwd();
1484
1584
  let checksum = null;
1585
+ let stack = null;
1485
1586
  try {
1486
1587
  const manifest = await scanLockfile(cwd);
1487
1588
  for (const warning of manifest.warnings ?? []) {
@@ -1489,6 +1590,7 @@ async function runMarkBuild(args) {
1489
1590
  }
1490
1591
  const { payload } = buildWirePayload(manifest);
1491
1592
  checksum = computeManifestChecksum(payload.packages);
1593
+ stack = detectStack(payload.packages);
1492
1594
  } catch (err) {
1493
1595
  console.warn(
1494
1596
  `mark-build: could not compute the build fingerprint (${err.message}). Stamping the production flag only.`
@@ -1506,7 +1608,7 @@ async function runMarkBuild(args) {
1506
1608
  console.warn(`mark-build: no HTML files found under ${dir}. Nothing to mark.`);
1507
1609
  return 0;
1508
1610
  }
1509
- const snippet = buildInjectionSnippet(checksum);
1611
+ const snippet = buildInjectionSnippet(checksum, stack);
1510
1612
  let marked = 0;
1511
1613
  for (const file of files) {
1512
1614
  const before = readFileSync2(file, "utf8");
@@ -1516,8 +1618,9 @@ async function runMarkBuild(args) {
1516
1618
  marked += 1;
1517
1619
  }
1518
1620
  }
1621
+ const stackSummary = stack !== null ? describeStack(stack) : null;
1519
1622
  console.log(
1520
- `mark-build: marked ${marked} HTML file(s) in ${dir}${checksum !== null ? ` (build ${checksum})` : ""}.`
1623
+ `mark-build: marked ${marked} HTML file(s) in ${dir}${checksum !== null ? ` (build ${checksum})` : ""}${stackSummary !== null ? ` [${stackSummary}]` : ""}.`
1521
1624
  );
1522
1625
  return 0;
1523
1626
  }