@varlock/cloudflare-integration 1.1.0 → 1.1.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/dist/index.d.ts CHANGED
@@ -10,6 +10,10 @@ import { PluginConfig } from '@cloudflare/vite-plugin';
10
10
  * `@cloudflare/vite-plugin` (which doesn't support SvelteKit) and uses an
11
11
  * SSR-entry-based env loader.
12
12
  *
13
+ * **Important:** Do not use a `.dev.vars` file alongside this plugin — varlock
14
+ * handles env injection automatically. The plugin will throw an error if a
15
+ * `.dev.vars` file is detected in your project root or build output.
16
+ *
13
17
  * @example
14
18
  * ```ts
15
19
  * import { varlockCloudflareVitePlugin } from '@varlock/cloudflare-integration';
package/dist/index.js CHANGED
@@ -1,4 +1,6 @@
1
- import path from 'path';
1
+ import path2 from 'path';
2
+ import { existsSync, readdirSync, writeFileSync, unlinkSync } from 'fs';
3
+ import { execSync, spawn } from 'child_process';
2
4
  import { initVarlockEnv } from 'varlock/env';
3
5
  import { patchGlobalConsole } from 'varlock/patch-console';
4
6
  import { patchGlobalServerResponse } from 'varlock/patch-server-response';
@@ -7,7 +9,7 @@ import { createDebug } from 'varlock';
7
9
  import { execSyncVarlock, VarlockExecError } from 'varlock/exec-sync-varlock';
8
10
  import { cloudflare } from '@cloudflare/vite-plugin';
9
11
 
10
- // ../vite/dist/index.js
12
+ // src/index.ts
11
13
  var __create = Object.create;
12
14
  var __defProp = Object.defineProperty;
13
15
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -34,7 +36,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
34
36
  mod
35
37
  ));
36
38
  var require_ast_matcher = __commonJS({
37
- "../../../node_modules/.bun/ast-matcher@1.2.0/node_modules/ast-matcher/index.js"(exports$1, module) {
39
+ "../../../node_modules/.bun/ast-matcher@1.2.0/node_modules/ast-matcher/index.js"(exports, module) {
38
40
  var STOP = false;
39
41
  var SKIP_BRANCH = 1;
40
42
  var IGNORED_KEYS = ["start", "end", "loc", "location", "locations", "line", "column", "range", "ranges", "raw", "extra"];
@@ -1439,10 +1441,46 @@ function reloadConfig(cwd) {
1439
1441
  resetStaticReplacements();
1440
1442
  }
1441
1443
  reloadConfig();
1444
+ var VARLOCK_INIT_MODULE_ID = "\0varlock-ssr-init";
1442
1445
  function varlockVitePlugin(vitePluginOptions) {
1446
+ function buildInitModuleCode() {
1447
+ const ssrInjectMode = vitePluginOptions?.ssrInjectMode ?? "init-only";
1448
+ const lines = [
1449
+ "// Virtual module generated by @varlock/vite-integration",
1450
+ "// Runs before any user code to ensure ENV is available at module top-level",
1451
+ "globalThis.__varlockThrowOnMissingKeys = true;"
1452
+ ];
1453
+ if (ssrInjectMode === "auto-load") {
1454
+ lines.push("import 'varlock/auto-load';");
1455
+ } else {
1456
+ if (ssrInjectMode === "resolved-env") {
1457
+ lines.push(`globalThis.__varlockLoadedEnv = ${JSON.stringify(varlockLoadedEnv)};`);
1458
+ }
1459
+ if (vitePluginOptions?.ssrEntryCode?.length) {
1460
+ lines.push(...vitePluginOptions.ssrEntryCode);
1461
+ }
1462
+ lines.push(
1463
+ "import { initVarlockEnv } from 'varlock/env';",
1464
+ "import { patchGlobalConsole } from 'varlock/patch-console';",
1465
+ "import { patchGlobalResponse } from 'varlock/patch-response';"
1466
+ );
1467
+ lines.push(
1468
+ "initVarlockEnv();",
1469
+ "patchGlobalConsole();"
1470
+ );
1471
+ lines.push("patchGlobalResponse();");
1472
+ }
1473
+ return lines.join("\n");
1474
+ }
1443
1475
  return {
1444
1476
  name: "inject-varlock-config",
1445
1477
  enforce: "post",
1478
+ resolveId(id) {
1479
+ if (id === VARLOCK_INIT_MODULE_ID) return id;
1480
+ },
1481
+ load(id) {
1482
+ if (id === VARLOCK_INIT_MODULE_ID) return buildInitModuleCode();
1483
+ },
1446
1484
  // hook to modify config before it is resolved
1447
1485
  async config(config, env) {
1448
1486
  debug("vite plugin - config fn called");
@@ -1461,8 +1499,8 @@ See https://varlock.dev/integrations/vite/ for more details.
1461
1499
  `);
1462
1500
  }
1463
1501
  isDevCommand = env.command === "serve";
1464
- const projectRoot = config.root ? path.resolve(config.root) : void 0;
1465
- const rootDiffersFromCwd = !!(projectRoot && path.relative(projectRoot, process.cwd()) !== "");
1502
+ const projectRoot = config.root ? path2.resolve(config.root) : void 0;
1503
+ const rootDiffersFromCwd = !!(projectRoot && path2.relative(projectRoot, process.cwd()) !== "");
1466
1504
  if (rootDiffersFromCwd) {
1467
1505
  reloadConfig(projectRoot);
1468
1506
  } else if (isFirstLoad) {
@@ -1496,7 +1534,7 @@ See https://varlock.dev/integrations/vite/ for more details.
1496
1534
  for (const varlockSource of varlockLoadedEnv.sources) {
1497
1535
  if (!varlockSource.enabled) continue;
1498
1536
  if (varlockLoadedEnv.basePath && varlockSource.path) {
1499
- config.configFileDependencies.push(path.resolve(varlockLoadedEnv.basePath, varlockSource.path));
1537
+ config.configFileDependencies.push(path2.resolve(varlockLoadedEnv.basePath, varlockSource.path));
1500
1538
  }
1501
1539
  }
1502
1540
  },
@@ -1522,51 +1560,27 @@ See https://varlock.dev/integrations/vite/ for more details.
1522
1560
  const fileExt = id.split("?")[0].split("#")[0].split(".").pop() || "";
1523
1561
  let isEntry = false;
1524
1562
  if (SUPPORTED_FILES.includes(fileExt)) {
1525
- const moduleIds = Array.from(this.getModuleIds());
1526
- if (moduleIds[0] === id) isEntry = true;
1563
+ try {
1564
+ const moduleInfo = this.getModuleInfo(id);
1565
+ if (moduleInfo?.isEntry) isEntry = true;
1566
+ } catch {
1567
+ }
1568
+ if (!isEntry) {
1569
+ const moduleIds = Array.from(this.getModuleIds());
1570
+ if (moduleIds[0] === id) isEntry = true;
1571
+ }
1527
1572
  }
1528
1573
  if (vitePluginOptions?.ssrEntryModuleIds?.includes(id)) isEntry = true;
1529
1574
  if (isEntry) {
1530
1575
  debug(`detected entry: ${id}`);
1531
- let isDevEnv = false;
1532
- if (this.environment) {
1533
- isDevEnv = this.environment.mode === "dev";
1534
- } else {
1535
- isDevEnv = isDevCommand;
1536
- }
1537
- const injectCode = [
1538
- "// INJECTED BY @varlock/vite-integration ----",
1539
- "globalThis.__varlockThrowOnMissingKeys = true;"
1540
- ];
1576
+ const injectCode = ["// INJECTED BY @varlock/vite-integration ----"];
1541
1577
  if (options?.ssr) {
1542
- const ssrInjectMode = vitePluginOptions?.ssrInjectMode ?? "init-only";
1543
- debug("ssrInjectMode =", ssrInjectMode, "isDev =", isDevEnv);
1544
- if (ssrInjectMode === "auto-load") {
1545
- injectCode.push(
1546
- "import 'varlock/auto-load';"
1547
- );
1548
- } else {
1549
- if (ssrInjectMode === "resolved-env") {
1550
- injectCode.push(`globalThis.__varlockLoadedEnv = ${JSON.stringify(varlockLoadedEnv)};`);
1551
- }
1552
- if (vitePluginOptions?.ssrEntryCode?.length) {
1553
- injectCode.push(...vitePluginOptions.ssrEntryCode);
1554
- }
1555
- injectCode.push(
1556
- "import { initVarlockEnv } from 'varlock/env';",
1557
- "import { patchGlobalConsole } from 'varlock/patch-console';",
1558
- "import { patchGlobalResponse } from 'varlock/patch-response';"
1559
- );
1560
- injectCode.push(
1561
- "initVarlockEnv();",
1562
- "patchGlobalConsole();"
1563
- );
1564
- injectCode.push("patchGlobalResponse();");
1565
- }
1578
+ injectCode.push(`import '${VARLOCK_INIT_MODULE_ID}';`);
1566
1579
  } else {
1580
+ injectCode.push("globalThis.__varlockThrowOnMissingKeys = true;");
1581
+ const isDevEnv = this.environment ? this.environment.mode === "dev" : isDevCommand;
1567
1582
  if (isDevEnv) {
1568
1583
  injectCode.push(
1569
- "// NOTE - __varlockValidKeys is only injected during development",
1570
1584
  `globalThis.__varlockValidKeys = ${JSON.stringify(Object.keys(varlockLoadedEnv?.config || {}))};`
1571
1585
  );
1572
1586
  }
@@ -1656,7 +1670,101 @@ if (typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Work
1656
1670
  `;
1657
1671
 
1658
1672
  // src/index.ts
1673
+ var isWindows = process.platform === "win32";
1659
1674
  var CLOUDFLARE_PLUGIN_NAME = "vite-plugin-cloudflare";
1675
+ var CF_SECRET_MAX_BYTES = 5120;
1676
+ function findDevVarsPath(root) {
1677
+ const distDir = path2.resolve(root, "dist");
1678
+ if (!existsSync(distDir)) return void 0;
1679
+ for (const entry of readdirSync(distDir, { withFileTypes: true })) {
1680
+ if (!entry.isDirectory()) continue;
1681
+ const wranglerPath = path2.join(distDir, entry.name, "wrangler.json");
1682
+ if (existsSync(wranglerPath)) {
1683
+ return path2.join(distDir, entry.name, ".dev.vars");
1684
+ }
1685
+ }
1686
+ return void 0;
1687
+ }
1688
+ function cleanupFile(filePath) {
1689
+ try {
1690
+ unlinkSync(filePath);
1691
+ } catch {
1692
+ }
1693
+ }
1694
+ function chunkString(str, maxBytes) {
1695
+ const chunks = [];
1696
+ let current = "";
1697
+ let currentBytes = 0;
1698
+ for (const char of str) {
1699
+ const charBytes = Buffer.byteLength(char);
1700
+ if (currentBytes + charBytes > maxBytes && current) {
1701
+ chunks.push(current);
1702
+ current = "";
1703
+ currentBytes = 0;
1704
+ }
1705
+ current += char;
1706
+ currentBytes += charBytes;
1707
+ }
1708
+ if (current) chunks.push(current);
1709
+ return chunks;
1710
+ }
1711
+ function formatEnvLine(key, value) {
1712
+ if (!value.includes("'")) {
1713
+ return `${key}='${value}'`;
1714
+ }
1715
+ const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n");
1716
+ return `${key}="${escaped}"`;
1717
+ }
1718
+ function formatDevVarsContent(graph, serializedGraph) {
1719
+ const lines = [];
1720
+ for (const key in graph.config) {
1721
+ const item = graph.config[key];
1722
+ if (item.value === void 0) continue;
1723
+ const strValue = typeof item.value === "string" ? item.value : JSON.stringify(item.value);
1724
+ lines.push(formatEnvLine(key, strValue));
1725
+ }
1726
+ if (Buffer.byteLength(serializedGraph) <= CF_SECRET_MAX_BYTES) {
1727
+ lines.push(formatEnvLine("__VARLOCK_ENV", serializedGraph));
1728
+ } else {
1729
+ const chunks = chunkString(serializedGraph, CF_SECRET_MAX_BYTES);
1730
+ lines.push(formatEnvLine("__VARLOCK_ENV_CHUNKS", String(chunks.length)));
1731
+ for (let i = 0; i < chunks.length; i++) {
1732
+ lines.push(formatEnvLine(`__VARLOCK_ENV_${i}`, chunks[i]));
1733
+ }
1734
+ }
1735
+ return lines.join("\n");
1736
+ }
1737
+ function serveFifoOrFile(filePath, content) {
1738
+ let fifoProcess;
1739
+ if (isWindows) {
1740
+ writeFileSync(filePath, content);
1741
+ } else {
1742
+ execSync(`mkfifo -m 0600 "${filePath}"`);
1743
+ const encoded = Buffer.from(content).toString("base64");
1744
+ const parentPid = process.pid;
1745
+ fifoProcess = spawn(process.execPath, [
1746
+ "-e",
1747
+ `
1748
+ const fs = require('fs');
1749
+ const content = Buffer.from('${encoded}', 'base64').toString();
1750
+ // Exit if the parent process dies (orphan protection).
1751
+ setInterval(() => {
1752
+ try { process.kill(${parentPid}, 0); }
1753
+ catch { process.exit(); }
1754
+ }, 2000);
1755
+ (function serve() {
1756
+ try { fs.writeFileSync(${JSON.stringify(filePath)}, content); setImmediate(serve); }
1757
+ catch { process.exit(); }
1758
+ })();
1759
+ `
1760
+ ], { stdio: ["ignore", "ignore", "ignore"] });
1761
+ }
1762
+ return {
1763
+ stop() {
1764
+ fifoProcess?.kill();
1765
+ }
1766
+ };
1767
+ }
1660
1768
  function varlockCloudflareVitePlugin(cloudflareOptions) {
1661
1769
  const conflictGuard = {
1662
1770
  name: "varlock-cloudflare-conflict-guard",
@@ -1675,8 +1783,15 @@ function varlockCloudflareVitePlugin(cloudflareOptions) {
1675
1783
  const modeDetector = {
1676
1784
  name: "varlock-cloudflare-mode",
1677
1785
  enforce: "pre",
1678
- config(_config, env) {
1786
+ config(config, env) {
1679
1787
  isDevMode = env.command === "serve";
1788
+ const root = config.root ? path2.resolve(config.root) : process.cwd();
1789
+ const devVarsPath = path2.resolve(root, ".dev.vars");
1790
+ if (existsSync(devVarsPath)) {
1791
+ throw new Error(
1792
+ "[varlock] A .dev.vars file was found in your project root, which conflicts with varlock's env management.\nRemove the .dev.vars file \u2014 varlock handles env injection automatically."
1793
+ );
1794
+ }
1680
1795
  }
1681
1796
  };
1682
1797
  const userConfig = cloudflareOptions?.config;
@@ -1719,9 +1834,44 @@ function varlockCloudflareVitePlugin(cloudflareOptions) {
1719
1834
  ...cloudflareOptions,
1720
1835
  config: mergedConfig
1721
1836
  });
1837
+ let resolvedRoot = "";
1838
+ const previewEnvInjector = {
1839
+ name: "varlock-cloudflare-preview-env",
1840
+ configResolved(config) {
1841
+ resolvedRoot = config.root;
1842
+ },
1843
+ configurePreviewServer(server) {
1844
+ if (!resolvedRoot) return;
1845
+ const devVarsPath = findDevVarsPath(resolvedRoot);
1846
+ if (!devVarsPath) return;
1847
+ if (existsSync(devVarsPath)) {
1848
+ throw new Error(
1849
+ "[varlock] A .dev.vars file was found in the build output, which conflicts with varlock's env management.\nRemove your project-root .dev.vars file \u2014 varlock handles env injection automatically."
1850
+ );
1851
+ }
1852
+ const serializedGraph = process.env.__VARLOCK_ENV;
1853
+ if (!serializedGraph || !varlockLoadedEnv) return;
1854
+ const content = formatDevVarsContent(varlockLoadedEnv, serializedGraph);
1855
+ const fifo = serveFifoOrFile(devVarsPath, content);
1856
+ const origClose = server.close.bind(server);
1857
+ server.close = async () => {
1858
+ fifo.stop();
1859
+ cleanupFile(devVarsPath);
1860
+ return origClose();
1861
+ };
1862
+ const onExit = () => {
1863
+ fifo.stop();
1864
+ cleanupFile(devVarsPath);
1865
+ };
1866
+ process.on("exit", onExit);
1867
+ process.on("SIGINT", onExit);
1868
+ process.on("SIGTERM", onExit);
1869
+ }
1870
+ };
1722
1871
  return [
1723
1872
  conflictGuard,
1724
1873
  modeDetector,
1874
+ previewEnvInjector,
1725
1875
  varlockPlugin,
1726
1876
  // cloudflare() may return a single plugin or an array
1727
1877
  ...Array.isArray(cloudflarePlugin) ? cloudflarePlugin : [cloudflarePlugin]