@timber-js/app 0.1.23 → 0.1.25

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.
Files changed (61) hide show
  1. package/dist/_chunks/{ssr-data-B2yikEEB.js → ssr-data-DLnbYpj1.js} +2 -4
  2. package/dist/_chunks/{ssr-data-B2yikEEB.js.map → ssr-data-DLnbYpj1.js.map} +1 -1
  3. package/dist/_chunks/{use-cookie-D5aS4slY.js → use-cookie-dDbpCTx-.js} +2 -2
  4. package/dist/_chunks/{use-cookie-D5aS4slY.js.map → use-cookie-dDbpCTx-.js.map} +1 -1
  5. package/dist/adapters/nitro.d.ts.map +1 -1
  6. package/dist/adapters/nitro.js +4 -3
  7. package/dist/adapters/nitro.js.map +1 -1
  8. package/dist/cli.js +1 -1
  9. package/dist/cli.js.map +1 -1
  10. package/dist/client/browser-dev.d.ts +29 -0
  11. package/dist/client/browser-dev.d.ts.map +1 -0
  12. package/dist/client/browser-links.d.ts +32 -0
  13. package/dist/client/browser-links.d.ts.map +1 -0
  14. package/dist/client/error-boundary.js +1 -1
  15. package/dist/client/index.d.ts +2 -0
  16. package/dist/client/index.d.ts.map +1 -1
  17. package/dist/client/index.js +150 -122
  18. package/dist/client/index.js.map +1 -1
  19. package/dist/client/navigation-context.d.ts +52 -0
  20. package/dist/client/navigation-context.d.ts.map +1 -0
  21. package/dist/client/router.d.ts.map +1 -1
  22. package/dist/client/transition-root.d.ts +54 -0
  23. package/dist/client/transition-root.d.ts.map +1 -0
  24. package/dist/client/use-params.d.ts +35 -25
  25. package/dist/client/use-params.d.ts.map +1 -1
  26. package/dist/client/use-pathname.d.ts +11 -4
  27. package/dist/client/use-pathname.d.ts.map +1 -1
  28. package/dist/client/use-router.d.ts +14 -0
  29. package/dist/client/use-router.d.ts.map +1 -1
  30. package/dist/cookies/index.js +2 -2
  31. package/dist/server/index.js +264 -218
  32. package/dist/server/index.js.map +1 -1
  33. package/dist/server/metadata-platform.d.ts +34 -0
  34. package/dist/server/metadata-platform.d.ts.map +1 -0
  35. package/dist/server/metadata-render.d.ts.map +1 -1
  36. package/dist/server/metadata-social.d.ts +24 -0
  37. package/dist/server/metadata-social.d.ts.map +1 -0
  38. package/dist/server/pipeline-interception.d.ts +32 -0
  39. package/dist/server/pipeline-interception.d.ts.map +1 -0
  40. package/dist/server/pipeline-metadata.d.ts +31 -0
  41. package/dist/server/pipeline-metadata.d.ts.map +1 -0
  42. package/dist/server/pipeline.d.ts.map +1 -1
  43. package/package.json +1 -1
  44. package/src/adapters/nitro.ts +9 -7
  45. package/src/cli.ts +9 -2
  46. package/src/client/browser-dev.ts +142 -0
  47. package/src/client/browser-entry.ts +73 -223
  48. package/src/client/browser-links.ts +90 -0
  49. package/src/client/index.ts +4 -0
  50. package/src/client/navigation-context.ts +118 -0
  51. package/src/client/router.ts +37 -33
  52. package/src/client/transition-root.tsx +86 -0
  53. package/src/client/use-params.ts +50 -54
  54. package/src/client/use-pathname.ts +31 -24
  55. package/src/client/use-router.ts +17 -15
  56. package/src/server/metadata-platform.ts +229 -0
  57. package/src/server/metadata-render.ts +9 -363
  58. package/src/server/metadata-social.ts +184 -0
  59. package/src/server/pipeline-interception.ts +76 -0
  60. package/src/server/pipeline-metadata.ts +90 -0
  61. package/src/server/pipeline.ts +2 -148
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Platform-specific metadata rendering — icons, Apple Web App, App Links, iTunes.
3
+ *
4
+ * Extracted from metadata-render.ts to keep files under 500 lines.
5
+ *
6
+ * See design/16-metadata.md
7
+ */
8
+ import type { Metadata } from './types.js';
9
+ import type { HeadElement } from './metadata.js';
10
+ /**
11
+ * Render icon link elements (favicon, shortcut, apple-touch-icon, custom).
12
+ */
13
+ export declare function renderIcons(icons: NonNullable<Metadata['icons']>, elements: HeadElement[]): void;
14
+ /**
15
+ * Render alternate link elements (canonical, hreflang, media, types).
16
+ */
17
+ export declare function renderAlternates(alternates: NonNullable<Metadata['alternates']>, elements: HeadElement[]): void;
18
+ /**
19
+ * Render site verification meta tags (Google, Yahoo, Yandex, custom).
20
+ */
21
+ export declare function renderVerification(verification: NonNullable<Metadata['verification']>, elements: HeadElement[]): void;
22
+ /**
23
+ * Render Apple Web App meta tags and startup image links.
24
+ */
25
+ export declare function renderAppleWebApp(appleWebApp: NonNullable<Metadata['appleWebApp']>, elements: HeadElement[]): void;
26
+ /**
27
+ * Render App Links (al:*) meta tags for deep linking across platforms.
28
+ */
29
+ export declare function renderAppLinks(appLinks: NonNullable<Metadata['appLinks']>, elements: HeadElement[]): void;
30
+ /**
31
+ * Render Apple iTunes smart banner meta tag.
32
+ */
33
+ export declare function renderItunes(itunes: NonNullable<Metadata['itunes']>, elements: HeadElement[]): void;
34
+ //# sourceMappingURL=metadata-platform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata-platform.d.ts","sourceRoot":"","sources":["../../src/server/metadata-platform.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,IAAI,CA6ChG;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,WAAW,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,EAC/C,QAAQ,EAAE,WAAW,EAAE,GACtB,IAAI,CA+BN;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,EACnD,QAAQ,EAAE,WAAW,EAAE,GACtB,IAAI,CAkBN;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,WAAW,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,EACjD,QAAQ,EAAE,WAAW,EAAE,GACtB,IAAI,CAmCN;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,EAC3C,QAAQ,EAAE,WAAW,EAAE,GACtB,IAAI,CAwCN;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,IAAI,CAQnG"}
@@ -1 +1 @@
1
- {"version":3,"file":"metadata-render.d.ts","sourceRoot":"","sources":["../../src/server/metadata-render.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAIjD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,QAAQ,GAAG,WAAW,EAAE,CAkI1E"}
1
+ {"version":3,"file":"metadata-render.d.ts","sourceRoot":"","sources":["../../src/server/metadata-render.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAajD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,QAAQ,GAAG,WAAW,EAAE,CAkI1E"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Social metadata rendering — Open Graph and Twitter Card meta tags.
3
+ *
4
+ * Extracted from metadata-render.ts to keep files under 500 lines.
5
+ *
6
+ * See design/16-metadata.md
7
+ */
8
+ import type { Metadata } from './types.js';
9
+ import type { HeadElement } from './metadata.js';
10
+ /**
11
+ * Render Open Graph metadata into head element descriptors.
12
+ *
13
+ * Handles og:title, og:description, og:image (with dimensions/alt),
14
+ * og:video, og:audio, og:article:author, and other OG properties.
15
+ */
16
+ export declare function renderOpenGraph(og: NonNullable<Metadata['openGraph']>, elements: HeadElement[]): void;
17
+ /**
18
+ * Render Twitter Card metadata into head element descriptors.
19
+ *
20
+ * Handles twitter:card, twitter:site, twitter:title, twitter:image,
21
+ * twitter:player, and twitter:app (per-platform name/id/url).
22
+ */
23
+ export declare function renderTwitter(tw: NonNullable<Metadata['twitter']>, elements: HeadElement[]): void;
24
+ //# sourceMappingURL=metadata-social.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata-social.d.ts","sourceRoot":"","sources":["../../src/server/metadata-social.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,IAAI,CAoErG;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,IAAI,CA0FjG"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Interception route matching for the request pipeline.
3
+ *
4
+ * Matches target URLs against interception rewrites to support the
5
+ * modal route pattern (soft navigation intercepts).
6
+ *
7
+ * Extracted from pipeline.ts to keep files under 500 lines.
8
+ *
9
+ * See design/07-routing.md §"Intercepting Routes"
10
+ */
11
+ /** Result of a successful interception match. */
12
+ export interface InterceptionMatchResult {
13
+ /** The pathname to re-match (the source/intercepting route's parent). */
14
+ sourcePathname: string;
15
+ }
16
+ /**
17
+ * Check if an intercepting route applies for this soft navigation.
18
+ *
19
+ * Matches the target pathname against interception rewrites, constrained
20
+ * by the source URL (X-Timber-URL header — where the user navigates FROM).
21
+ *
22
+ * Returns the source pathname to re-match if interception applies, or null.
23
+ */
24
+ export declare function findInterceptionMatch(targetPathname: string, sourceUrl: string, rewrites: import('#/routing/interception.js').InterceptionRewrite[]): InterceptionMatchResult | null;
25
+ /**
26
+ * Check if a pathname matches a URL pattern with dynamic segments.
27
+ *
28
+ * Supports [param] (single segment) and [...param] (one or more segments).
29
+ * Static segments must match exactly.
30
+ */
31
+ export declare function pathnameMatchesPattern(pathname: string, pattern: string): boolean;
32
+ //# sourceMappingURL=pipeline-interception.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-interception.d.ts","sourceRoot":"","sources":["../../src/server/pipeline-interception.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,iDAAiD;AACjD,MAAM,WAAW,uBAAuB;IACtC,yEAAyE;IACzE,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,OAAO,2BAA2B,EAAE,mBAAmB,EAAE,GAClE,uBAAuB,GAAG,IAAI,CAYhC;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CA0BjF"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Metadata route helpers for the request pipeline.
3
+ *
4
+ * Handles serving static metadata files and serializing sitemap responses.
5
+ * Extracted from pipeline.ts to keep files under 500 lines.
6
+ *
7
+ * See design/16-metadata.md §"Metadata Routes"
8
+ */
9
+ /**
10
+ * Serve a static metadata file by reading it from disk.
11
+ *
12
+ * Static metadata route files (.xml, .txt, .json, .png, .ico, .svg, etc.)
13
+ * are served as-is with the appropriate Content-Type header.
14
+ * Text files include charset=utf-8; binary files do not.
15
+ *
16
+ * See design/16-metadata.md §"Metadata Routes"
17
+ */
18
+ export declare function serveStaticMetadataFile(metaMatch: import('./route-matcher.js').MetadataRouteMatch): Promise<Response>;
19
+ /**
20
+ * Serialize a sitemap array to XML.
21
+ * Follows the sitemap.org protocol: https://www.sitemaps.org/protocol.html
22
+ */
23
+ export declare function serializeSitemap(entries: Array<{
24
+ url: string;
25
+ lastModified?: string | Date;
26
+ changeFrequency?: string;
27
+ priority?: number;
28
+ }>): string;
29
+ /** Escape special XML characters. */
30
+ export declare function escapeXml(str: string): string;
31
+ //# sourceMappingURL=pipeline-metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-metadata.d.ts","sourceRoot":"","sources":["../../src/server/pipeline-metadata.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAgBH;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAC3C,SAAS,EAAE,OAAO,oBAAoB,EAAE,kBAAkB,GACzD,OAAO,CAAC,QAAQ,CAAC,CAYnB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,KAAK,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC,GACD,MAAM,CAoBR;AAED,qCAAqC;AACrC,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO7C"}
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/server/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAY,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAkC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAItD,sEAAsE;AACtE,MAAM,WAAW,UAAU;IACzB,mDAAmD;IACnD,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,uDAAuD;IACvD,UAAU,CAAC,EAAE,YAAY,CAAC;CAC3B;AAED,6DAA6D;AAC7D,MAAM,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,UAAU,GAAG,IAAI,CAAC;AAEnE,sEAAsE;AACtE,MAAM,MAAM,oBAAoB,GAAG,CACjC,QAAQ,EAAE,MAAM,KACb,OAAO,oBAAoB,EAAE,kBAAkB,GAAG,IAAI,CAAC;AAE5D,iEAAiE;AACjE,MAAM,WAAW,mBAAmB;IAClC,iEAAiE;IACjE,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,6DAA6D;AAC7D,MAAM,MAAM,aAAa,GAAG,CAC1B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,oBAAoB,EAAE,OAAO,EAC7B,YAAY,CAAC,EAAE,mBAAmB,KAC/B,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAElC,+DAA+D;AAC/D,MAAM,MAAM,iBAAiB,GAAG,CAC9B,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,OAAO,EACZ,eAAe,EAAE,OAAO,KACrB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAI1B,MAAM,WAAW,cAAc;IAC7B,iFAAiF;IACjF,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,OAAO,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;IACtD,qEAAqE;IACrE,UAAU,EAAE,YAAY,CAAC;IACzB,iGAAiG;IACjG,kBAAkB,CAAC,EAAE,oBAAoB,CAAC;IAC1C,kEAAkE;IAClE,MAAM,EAAE,aAAa,CAAC;IACtB,kEAAkE;IAClE,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,eAAe,EAAE,OAAO,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzF,kFAAkF;IAClF,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,gFAAgF;IAChF,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,yGAAyG;IACzG,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,OAAO,2BAA2B,EAAE,mBAAmB,EAAE,CAAC;IACjF;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD;;;;;;;;;;OAUG;IACH,mBAAmB,CAAC,EAAE,CACpB,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,OAAO,EACZ,eAAe,EAAE,OAAO,KACrB,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CACnC;AAID;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAuU1F"}
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/server/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAY,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAoC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAItD,sEAAsE;AACtE,MAAM,WAAW,UAAU;IACzB,mDAAmD;IACnD,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,uDAAuD;IACvD,UAAU,CAAC,EAAE,YAAY,CAAC;CAC3B;AAED,6DAA6D;AAC7D,MAAM,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,UAAU,GAAG,IAAI,CAAC;AAEnE,sEAAsE;AACtE,MAAM,MAAM,oBAAoB,GAAG,CACjC,QAAQ,EAAE,MAAM,KACb,OAAO,oBAAoB,EAAE,kBAAkB,GAAG,IAAI,CAAC;AAE5D,iEAAiE;AACjE,MAAM,WAAW,mBAAmB;IAClC,iEAAiE;IACjE,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,6DAA6D;AAC7D,MAAM,MAAM,aAAa,GAAG,CAC1B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,oBAAoB,EAAE,OAAO,EAC7B,YAAY,CAAC,EAAE,mBAAmB,KAC/B,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAElC,+DAA+D;AAC/D,MAAM,MAAM,iBAAiB,GAAG,CAC9B,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,OAAO,EACZ,eAAe,EAAE,OAAO,KACrB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAI1B,MAAM,WAAW,cAAc;IAC7B,iFAAiF;IACjF,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,OAAO,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;IACtD,qEAAqE;IACrE,UAAU,EAAE,YAAY,CAAC;IACzB,iGAAiG;IACjG,kBAAkB,CAAC,EAAE,oBAAoB,CAAC;IAC1C,kEAAkE;IAClE,MAAM,EAAE,aAAa,CAAC;IACtB,kEAAkE;IAClE,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,eAAe,EAAE,OAAO,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzF,kFAAkF;IAClF,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,gFAAgF;IAChF,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,yGAAyG;IACzG,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,OAAO,2BAA2B,EAAE,mBAAmB,EAAE,CAAC;IACjF;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD;;;;;;;;;;OAUG;IACH,mBAAmB,CAAC,EAAE,CACpB,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,OAAO,EACZ,eAAe,EAAE,OAAO,KACrB,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CACnC;AAID;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAuU1F"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timber-js/app",
3
- "version": "0.1.23",
3
+ "version": "0.1.25",
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",
@@ -239,7 +239,13 @@ export function generateNitroEntry(
239
239
  preset: NitroPreset,
240
240
  hasManifestInit = false
241
241
  ): string {
242
- const serverEntryRelative = relative(outDir, join(buildDir, 'server', 'entry.js'));
242
+ // The RSC entry is the main request handler — it exports the fetch handler as default.
243
+ // The Vite RSC plugin outputs it to rsc/index.js.
244
+ let serverEntryRelative = relative(outDir, join(buildDir, 'rsc', 'index.js'));
245
+ // Ensure the import path starts with ./ for ESM compatibility
246
+ if (!serverEntryRelative.startsWith('.')) {
247
+ serverEntryRelative = './' + serverEntryRelative;
248
+ }
243
249
  const runtimeName = PRESET_CONFIGS[preset].runtimeName;
244
250
  const earlyHints = PRESET_CONFIGS[preset].supportsEarlyHints;
245
251
 
@@ -250,10 +256,6 @@ export function generateNitroEntry(
250
256
  // On node-server and bun, wrap the handler with ALS so the pipeline
251
257
  // can send 103 Early Hints via res.writeEarlyHints(). Other presets
252
258
  // either don't support 103 or handle it at the CDN level.
253
- const earlyHintsImport = earlyHints
254
- ? `import { runWithEarlyHintsSender } from '${serverEntryRelative}'\n`
255
- : '';
256
-
257
259
  const handlerCall = earlyHints
258
260
  ? ` const nodeRes = event.node?.res
259
261
  const earlyHintsSender = (typeof nodeRes?.writeEarlyHints === 'function')
@@ -268,8 +270,8 @@ export function generateNitroEntry(
268
270
  return `// Generated by @timber-js/app/adapters/nitro
269
271
  // Do not edit — this file is regenerated on each build.
270
272
 
271
- ${manifestImport}${earlyHintsImport}import { defineEventHandler, toWebRequest, sendWebResponse } from 'h3'
272
- import { handler } from '${serverEntryRelative}'
273
+ ${manifestImport}import { defineEventHandler, toWebRequest, sendWebResponse } from 'h3'
274
+ import handler, { runWithEarlyHintsSender } from '${serverEntryRelative}'
273
275
 
274
276
  // Set TIMBER_RUNTIME for instrumentation.ts conditional SDK initialization.
275
277
  // See design/25-production-deployments.md §"TIMBER_RUNTIME".
package/src/cli.ts CHANGED
@@ -189,9 +189,16 @@ async function main(): Promise<void> {
189
189
  }
190
190
  }
191
191
 
192
- // Only run main when executed directly (not imported in tests)
192
+ // Run main when executed as a CLI (not imported in tests).
193
+ // The bin shim (bin/timber.mjs) does `import '../dist/cli.js'`, so
194
+ // process.argv[1] points to the shim, not this file. We check both:
195
+ // direct execution AND being imported by the timber bin shim.
193
196
  const isDirectExecution =
194
- typeof process !== 'undefined' && process.argv[1] && import.meta.url.endsWith(process.argv[1]);
197
+ typeof process !== 'undefined' &&
198
+ process.argv[1] &&
199
+ (import.meta.url.endsWith(process.argv[1]) ||
200
+ process.argv[1].endsWith('bin/timber.mjs') ||
201
+ process.argv[1].endsWith('bin/timber'));
195
202
 
196
203
  if (isDirectExecution) {
197
204
  main().catch((err) => {
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Dev-only browser helpers — server log replay and client error forwarding.
3
+ *
4
+ * These are only active when import.meta.hot is available (Vite dev mode).
5
+ * Extracted from browser-entry.ts to keep files under 500 lines.
6
+ *
7
+ * See design/21-dev-server.md §"HMR Wiring"
8
+ */
9
+
10
+ import { isPageUnloading } from './unload-guard.js';
11
+
12
+ // ─── HMR Hot Interface ──────────────────────────────────────────────
13
+
14
+ /** Minimal interface for Vite's HMR channel. */
15
+ export interface HotInterface {
16
+ on(event: string, cb: (...args: unknown[]) => void): void;
17
+ send(event: string, data: unknown): void;
18
+ }
19
+
20
+ // ─── Server Log Replay ──────────────────────────────────────────────
21
+
22
+ /** Payload shape from plugins/dev-logs.ts */
23
+ interface ServerLogPayload {
24
+ level: 'log' | 'warn' | 'error' | 'debug' | 'info';
25
+ args: unknown[];
26
+ location: string | null;
27
+ timestamp: number;
28
+ }
29
+
30
+ /**
31
+ * Deserialize a serialized arg back into a console-friendly value.
32
+ *
33
+ * Handles Error objects (serialized as { __type: 'Error', ... }),
34
+ * Maps, Sets, and passes everything else through.
35
+ */
36
+ function deserializeArg(arg: unknown): unknown {
37
+ if (arg === '[undefined]') return undefined;
38
+ if (arg === null || typeof arg !== 'object') return arg;
39
+
40
+ const obj = arg as Record<string, unknown>;
41
+
42
+ if (obj.__type === 'Error') {
43
+ const err = new Error(obj.message as string);
44
+ err.name = obj.name as string;
45
+ if (obj.stack) err.stack = obj.stack as string;
46
+ return err;
47
+ }
48
+
49
+ if (obj.__type === 'Map') {
50
+ return new Map(
51
+ Object.entries(obj.entries as Record<string, unknown>).map(([k, v]) => [k, deserializeArg(v)])
52
+ );
53
+ }
54
+
55
+ if (obj.__type === 'Set') {
56
+ return new Set((obj.values as unknown[]).map(deserializeArg));
57
+ }
58
+
59
+ if (Array.isArray(arg)) {
60
+ return arg.map(deserializeArg);
61
+ }
62
+
63
+ // Plain object — recurse
64
+ const result: Record<string, unknown> = {};
65
+ for (const [key, value] of Object.entries(obj)) {
66
+ result[key] = deserializeArg(value);
67
+ }
68
+ return result;
69
+ }
70
+
71
+ /**
72
+ * Set up the HMR listener that replays server console output in the browser.
73
+ *
74
+ * Each message arrives with a log level and serialized args. We prepend
75
+ * a styled "[SERVER]" badge and call the matching console method.
76
+ */
77
+ export function setupServerLogReplay(hot: Pick<HotInterface, 'on'>): void {
78
+ /** CSS styles for the [SERVER] badge in browser console. */
79
+ const BADGE_STYLES: Record<string, string> = {
80
+ log: 'background: #0070f3; color: white; padding: 1px 5px; border-radius: 3px; font-weight: bold;',
81
+ info: 'background: #0070f3; color: white; padding: 1px 5px; border-radius: 3px; font-weight: bold;',
82
+ warn: 'background: #f5a623; color: white; padding: 1px 5px; border-radius: 3px; font-weight: bold;',
83
+ error:
84
+ 'background: #e00; color: white; padding: 1px 5px; border-radius: 3px; font-weight: bold;',
85
+ debug:
86
+ 'background: #666; color: white; padding: 1px 5px; border-radius: 3px; font-weight: bold;',
87
+ };
88
+
89
+ hot.on('timber:server-log', (data: unknown) => {
90
+ const payload = data as ServerLogPayload;
91
+ const level = payload.level;
92
+ const fn = console[level] ?? console.log;
93
+ const args = payload.args.map(deserializeArg);
94
+
95
+ const badge = `%cSERVER`;
96
+ const style = BADGE_STYLES[level] ?? BADGE_STYLES.log;
97
+ const locationSuffix = payload.location ? ` (${payload.location})` : '';
98
+
99
+ fn.call(console, badge, style, ...args, locationSuffix ? `\n → ${payload.location}` : '');
100
+ });
101
+ }
102
+
103
+ // ─── Client Error Forwarding ────────────────────────────────────────
104
+
105
+ /**
106
+ * Set up global error handlers that forward uncaught client-side
107
+ * errors to the dev server via Vite's HMR channel.
108
+ *
109
+ * The server receives 'timber:client-error' events, and echoes them
110
+ * back as Vite '{ type: "error" }' payloads to trigger the overlay.
111
+ */
112
+ export function setupClientErrorForwarding(hot: Pick<HotInterface, 'send'>): void {
113
+ window.addEventListener('error', (event: ErrorEvent) => {
114
+ // Skip errors without useful information
115
+ if (!event.error && !event.message) return;
116
+ // Skip errors during page unload — these are abort-related, not application errors
117
+ if (isPageUnloading()) return;
118
+
119
+ const error = event.error;
120
+ hot.send('timber:client-error', {
121
+ message: error?.message ?? event.message,
122
+ stack: error?.stack ?? '',
123
+ componentStack: error?.componentStack ?? null,
124
+ });
125
+ });
126
+
127
+ window.addEventListener('unhandledrejection', (event: PromiseRejectionEvent) => {
128
+ const reason = event.reason;
129
+ if (!reason) return;
130
+ // Skip rejections during page unload — aborted fetches/streams cause these
131
+ if (isPageUnloading()) return;
132
+
133
+ const message = reason instanceof Error ? reason.message : String(reason);
134
+ const stack = reason instanceof Error ? (reason.stack ?? '') : '';
135
+
136
+ hot.send('timber:client-error', {
137
+ message,
138
+ stack,
139
+ componentStack: null,
140
+ });
141
+ });
142
+ }