hadars 0.2.0 → 0.2.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.
package/dist/cli.js CHANGED
@@ -1180,19 +1180,23 @@ var getReactResponse = async (req, opts) => {
1180
1180
  };
1181
1181
  const unsuspend = { cache: /* @__PURE__ */ new Map() };
1182
1182
  globalThis.__hadarsUnsuspend = unsuspend;
1183
+ globalThis.__hadarsContext = context;
1183
1184
  const element = createElement(App, props);
1184
1185
  try {
1185
1186
  await renderPreflight(element);
1186
1187
  } finally {
1187
1188
  globalThis.__hadarsUnsuspend = null;
1189
+ globalThis.__hadarsContext = null;
1188
1190
  }
1189
1191
  const status = context.head.status;
1190
1192
  const getAppBody = async () => {
1191
1193
  globalThis.__hadarsUnsuspend = unsuspend;
1194
+ globalThis.__hadarsContext = context;
1192
1195
  try {
1193
1196
  return await renderToString(element);
1194
1197
  } finally {
1195
1198
  globalThis.__hadarsUnsuspend = null;
1199
+ globalThis.__hadarsContext = null;
1196
1200
  }
1197
1201
  };
1198
1202
  const finalize = async () => {
@@ -2497,6 +2501,67 @@ async function loadConfig(configPath) {
2497
2501
  const mod = await import(url);
2498
2502
  return mod && (mod.default ?? mod);
2499
2503
  }
2504
+ async function bundleCloudflare(config, configPath, outputFile, cwd) {
2505
+ console.log("Building hadars project...");
2506
+ await build({ ...config, mode: "production" });
2507
+ const ssrBundle = resolve(cwd, ".hadars", "index.ssr.js");
2508
+ const outHtml = resolve(cwd, ".hadars", "static", "out.html");
2509
+ if (!existsSync3(ssrBundle)) {
2510
+ console.error(`SSR bundle not found: ${ssrBundle}`);
2511
+ process.exit(1);
2512
+ }
2513
+ if (!existsSync3(outHtml)) {
2514
+ console.error(`HTML template not found: ${outHtml}`);
2515
+ process.exit(1);
2516
+ }
2517
+ const cloudflareModule = resolve(dirname(fileURLToPath3(import.meta.url)), "cloudflare.js");
2518
+ const shimPath = join(cwd, `.hadars-cloudflare-shim-${Date.now()}.ts`);
2519
+ const shim = [
2520
+ `import * as ssrModule from ${JSON.stringify(ssrBundle)};`,
2521
+ `import outHtml from ${JSON.stringify(outHtml)};`,
2522
+ `import { createCloudflareHandler } from ${JSON.stringify(cloudflareModule)};`,
2523
+ `import config from ${JSON.stringify(configPath)};`,
2524
+ `export default createCloudflareHandler(config as any, { ssrModule: ssrModule as any, outHtml });`
2525
+ ].join("\n") + "\n";
2526
+ await writeFile(shimPath, shim, "utf-8");
2527
+ try {
2528
+ const { build: esbuild } = await import("esbuild");
2529
+ console.log(`Bundling Cloudflare Worker \u2192 ${outputFile}`);
2530
+ await esbuild({
2531
+ entryPoints: [shimPath],
2532
+ bundle: true,
2533
+ // 'browser' avoids Node.js built-in shims; CF Workers uses Web APIs.
2534
+ // If you use node:* APIs in your app code, add nodejs_compat to wrangler.toml.
2535
+ platform: "browser",
2536
+ format: "esm",
2537
+ target: ["es2022"],
2538
+ outfile: outputFile,
2539
+ sourcemap: false,
2540
+ loader: { ".html": "text", ".tsx": "tsx", ".ts": "ts" },
2541
+ // @rspack/* is build-time only — never imported at Worker runtime.
2542
+ external: ["@rspack/*"],
2543
+ // Cloudflare Workers supports the Web Crypto API natively; suppress
2544
+ // esbuild's attempt to polyfill node:crypto.
2545
+ define: { "global": "globalThis" }
2546
+ });
2547
+ console.log(`Cloudflare Worker bundle written to ${outputFile}`);
2548
+ console.log(`
2549
+ Deploy instructions:`);
2550
+ console.log(` 1. Ensure wrangler.toml points to the output file:`);
2551
+ console.log(` name = "my-app"`);
2552
+ console.log(` main = "${outputFile}"`);
2553
+ console.log(` compatibility_date = "2024-09-23"`);
2554
+ console.log(` compatibility_flags = ["nodejs_compat"]`);
2555
+ console.log(` 2. Upload .hadars/static/ assets to R2 (or another CDN):`);
2556
+ console.log(` wrangler r2 object put my-bucket/assets/ --file .hadars/static/ --recursive`);
2557
+ console.log(` 3. Add a route rule in wrangler.toml to send *.js / *.css to R2`);
2558
+ console.log(` and all other requests to the Worker.`);
2559
+ console.log(` 4. Deploy: wrangler deploy`);
2560
+ } finally {
2561
+ await unlink(shimPath).catch(() => {
2562
+ });
2563
+ }
2564
+ }
2500
2565
  async function bundleLambda(config, configPath, outputFile, cwd) {
2501
2566
  console.log("Building hadars project...");
2502
2567
  await build({ ...config, mode: "production" });
@@ -2598,7 +2663,7 @@ export default config;
2598
2663
  dist/
2599
2664
  `,
2600
2665
  "src/App.tsx": () => `import React from 'react';
2601
- import { HadarsContext, HadarsHead, type HadarsApp } from 'hadars';
2666
+ import { HadarsHead, type HadarsApp } from 'hadars';
2602
2667
 
2603
2668
  const css = \`
2604
2669
  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
@@ -2710,15 +2775,15 @@ const css = \`
2710
2775
 
2711
2776
  \`;
2712
2777
 
2713
- const App: HadarsApp<{}> = ({ context }) => {
2778
+ const App: HadarsApp<{}> = () => {
2714
2779
  const [count, setCount] = React.useState(0);
2715
2780
 
2716
2781
  return (
2717
- <HadarsContext context={context}>
2782
+ <>
2718
2783
  <HadarsHead status={200}>
2719
2784
  <title>My App</title>
2720
- <meta id="viewport" name="viewport" content="width=device-width, initial-scale=1" />
2721
- <style id="app-styles" dangerouslySetInnerHTML={{ __html: css }} />
2785
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
2786
+ <style data-id="app-styles" dangerouslySetInnerHTML={{ __html: css }} />
2722
2787
  </HadarsHead>
2723
2788
 
2724
2789
  <nav className="nav">
@@ -2776,7 +2841,7 @@ const App: HadarsApp<{}> = ({ context }) => {
2776
2841
  </div>
2777
2842
  </div>
2778
2843
 
2779
- </HadarsContext>
2844
+ </>
2780
2845
  );
2781
2846
  };
2782
2847
 
@@ -2805,7 +2870,7 @@ Done! Next steps:
2805
2870
  `);
2806
2871
  }
2807
2872
  function usage() {
2808
- console.log("Usage: hadars <new <name> | dev | build | run | export lambda [output.mjs]>");
2873
+ console.log("Usage: hadars <new <name> | dev | build | run | export lambda [output.mjs] | export cloudflare [output.mjs]>");
2809
2874
  }
2810
2875
  async function runCli(argv, cwd = process.cwd()) {
2811
2876
  const cmd = argv[2];
@@ -2848,13 +2913,18 @@ async function runCli(argv, cwd = process.cwd()) {
2848
2913
  process.exit(0);
2849
2914
  case "export": {
2850
2915
  const subCmd = argv[3];
2851
- if (subCmd !== "lambda") {
2852
- console.error(`Unknown export target: ${subCmd ?? "(none)"}. Did you mean: hadars export lambda`);
2916
+ if (subCmd === "lambda") {
2917
+ const outputFile = resolve(cwd, argv[4] ?? "lambda.mjs");
2918
+ await bundleLambda(cfg, configPath, outputFile, cwd);
2919
+ process.exit(0);
2920
+ } else if (subCmd === "cloudflare") {
2921
+ const outputFile = resolve(cwd, argv[4] ?? "cloudflare.mjs");
2922
+ await bundleCloudflare(cfg, configPath, outputFile, cwd);
2923
+ process.exit(0);
2924
+ } else {
2925
+ console.error(`Unknown export target: ${subCmd ?? "(none)"}. Supported: lambda, cloudflare`);
2853
2926
  process.exit(1);
2854
2927
  }
2855
- const outputFile = resolve(cwd, argv[4] ?? "lambda.mjs");
2856
- await bundleLambda(cfg, configPath, outputFile, cwd);
2857
- process.exit(0);
2858
2928
  }
2859
2929
  case "run":
2860
2930
  console.log("Running project...");