@timber-js/app 0.1.34 → 0.1.36

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timber-js/app",
3
- "version": "0.1.34",
3
+ "version": "0.1.36",
4
4
  "description": "Vite-native React framework for Cloudflare Workers — correct HTTP semantics, real status codes, pages that work without JavaScript",
5
5
  "keywords": [
6
6
  "cloudflare-workers",
@@ -87,7 +87,8 @@
87
87
  "dependencies": {
88
88
  "@opentelemetry/api": "^1.9.0",
89
89
  "@opentelemetry/context-async-hooks": "^2.6.0",
90
- "@opentelemetry/sdk-trace-base": "^2.6.0"
90
+ "@opentelemetry/sdk-trace-base": "^2.6.0",
91
+ "nitro": "^3.0.0"
91
92
  },
92
93
  "peerDependencies": {
93
94
  "@content-collections/core": "^0.14.0",
@@ -206,6 +206,10 @@ export function nitro(options: NitroAdapterOptions = {}): TimberPlatformAdapter
206
206
  // Generate the Nitro config with static asset cache rules
207
207
  const nitroConfig = generateNitroConfig(preset, options.nitroConfig);
208
208
  await writeFile(join(outDir, 'nitro.config.ts'), nitroConfig);
209
+
210
+ // Run the Nitro build to produce a production-ready server bundle.
211
+ // The output goes to dist/nitro/.output/server/index.mjs (for node-server preset).
212
+ await runNitroBuild(outDir, preset, options.nitroConfig);
209
213
  },
210
214
 
211
215
  // Only presets that produce a locally-runnable server get preview().
@@ -276,7 +280,7 @@ export function generateNitroEntry(
276
280
  return `// Generated by @timber-js/app/adapters/nitro
277
281
  // Do not edit — this file is regenerated on each build.
278
282
 
279
- ${manifestImport}import { defineEventHandler, toWebRequest, sendWebResponse } from 'h3'
283
+ ${manifestImport}import { defineEventHandler, sendWebResponse } from 'nitro/h3'
280
284
  import handler, { runWithEarlyHintsSender } from '${serverEntryRelative}'
281
285
 
282
286
  // Set TIMBER_RUNTIME for instrumentation.ts conditional SDK initialization.
@@ -284,7 +288,8 @@ import handler, { runWithEarlyHintsSender } from '${serverEntryRelative}'
284
288
  process.env.TIMBER_RUNTIME = '${runtimeName}'
285
289
 
286
290
  export default defineEventHandler(async (event) => {
287
- const webRequest = toWebRequest(event)
291
+ // h3 v2: event.request is a standard Web Request
292
+ const webRequest = event.request
288
293
  ${handlerCall}
289
294
  return sendWebResponse(event, webResponse)
290
295
  })
@@ -300,6 +305,7 @@ export function generateNitroConfig(
300
305
 
301
306
  const config: Record<string, unknown> = {
302
307
  preset: presetConfig.nitroPreset,
308
+ entry: './entry.ts',
303
309
  output: { dir: presetConfig.outputDir },
304
310
  // Static asset cache headers — hashed assets are immutable, others get 1h.
305
311
  // See design/25-production-deployments.md §"CDN / Edge Cache"
@@ -315,7 +321,7 @@ export function generateNitroConfig(
315
321
  return `// Generated by @timber-js/app/adapters/nitro
316
322
  // Do not edit — this file is regenerated on each build.
317
323
 
318
- import { defineNitroConfig } from 'nitropack/config'
324
+ import { defineNitroConfig } from 'nitro/config'
319
325
 
320
326
  export default defineNitroConfig(${configJson})
321
327
  `;
@@ -521,6 +527,44 @@ export function generateNitroPreviewCommand(
521
527
  };
522
528
  }
523
529
 
530
+ /**
531
+ * Run the Nitro production build using the programmatic API.
532
+ * Uses dynamic import so nitro is only loaded at build time.
533
+ * Externalizes the timber RSC/SSR output — those files are pre-built
534
+ * by timber and have internal references that nitro's bundler can't follow.
535
+ */
536
+ async function runNitroBuild(
537
+ nitroDir: string,
538
+ preset: NitroPreset,
539
+ userConfig?: Record<string, unknown>
540
+ ): Promise<void> {
541
+ const presetConfig = PRESET_CONFIGS[preset];
542
+ const { createNitro, build: nitroBuild, prepare, copyPublicAssets } = await import('nitro');
543
+
544
+ const nitro = await createNitro({
545
+ rootDir: nitroDir,
546
+ preset: presetConfig.nitroPreset,
547
+ entry: join(nitroDir, 'entry.ts'),
548
+ output: { dir: join(nitroDir, presetConfig.outputDir) },
549
+ routeRules: {
550
+ '/assets/**': { headers: { 'Cache-Control': IMMUTABLE_CACHE } },
551
+ },
552
+ // Don't bundle the timber RSC/SSR build output — it has its own
553
+ // internal file references that nitro's bundler can't follow.
554
+ // Mark them as external so rollup leaves the imports as-is.
555
+ rollupConfig: {
556
+ external: [/\.\.\/rsc\//, /\.\/_timber-manifest-init/],
557
+ },
558
+ ...presetConfig.extraConfig,
559
+ ...userConfig,
560
+ });
561
+
562
+ await prepare(nitro);
563
+ await copyPublicAssets(nitro);
564
+ await nitroBuild(nitro);
565
+ await nitro.close();
566
+ }
567
+
524
568
  /** Spawn a Nitro preview process and pipe stdio. */
525
569
  function spawnNitroPreview(command: string, args: string[], cwd: string): Promise<void> {
526
570
  return new Promise<void>((resolve, reject) => {