@timber-js/app 0.2.0-alpha.209 → 0.2.0-alpha.210

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 (170) hide show
  1. package/dist/_chunks/{actions-BerlqoXA.js → actions-Rjk4htmA.js} +19 -25
  2. package/dist/_chunks/{actions-BerlqoXA.js.map → actions-Rjk4htmA.js.map} +1 -1
  3. package/dist/_chunks/als-registry-DaxkVjt5.js.map +1 -1
  4. package/dist/_chunks/{cache-api-CR23J_NC.js → cache-api-DGdYfNJn.js} +4 -4
  5. package/dist/_chunks/{cache-api-CR23J_NC.js.map → cache-api-DGdYfNJn.js.map} +1 -1
  6. package/dist/_chunks/{chains-CpFg56UB.js → chains-BoO51joc.js} +2 -2
  7. package/dist/_chunks/{chains-CpFg56UB.js.map → chains-BoO51joc.js.map} +1 -1
  8. package/dist/_chunks/{cli-check-C6Ev6wBO.js → cli-check-ajNY3B2e.js} +3 -3
  9. package/dist/_chunks/{cli-check-C6Ev6wBO.js.map → cli-check-ajNY3B2e.js.map} +1 -1
  10. package/dist/_chunks/{cli-schema-sync-CbT2AUUI.js → cli-schema-sync-D2eI8jEg.js} +2 -2
  11. package/dist/_chunks/{cli-schema-sync-CbT2AUUI.js.map → cli-schema-sync-D2eI8jEg.js.map} +1 -1
  12. package/dist/_chunks/{file-cache-Dw6BJPG7.js → codegen-Bps1sLKJ.js} +3 -29
  13. package/dist/_chunks/codegen-Bps1sLKJ.js.map +1 -0
  14. package/dist/_chunks/{convention-lint-jKTwKwPe.js → convention-lint-DLmhGsRS.js} +54 -316
  15. package/dist/_chunks/convention-lint-DLmhGsRS.js.map +1 -0
  16. package/dist/_chunks/{dev-server-C4WZdB7L.js → dev-server-v97rQH4b.js} +99 -9
  17. package/dist/_chunks/dev-server-v97rQH4b.js.map +1 -0
  18. package/dist/_chunks/{error-boundary-tA7kVfs4.js → error-boundary-DsNScGRM.js} +4 -4
  19. package/dist/_chunks/{error-boundary-tA7kVfs4.js.map → error-boundary-DsNScGRM.js.map} +1 -1
  20. package/dist/_chunks/{json-lossy-check-ip0Qi0MT.js → json-lossy-check-CVuRs2hG.js} +2 -2
  21. package/dist/_chunks/{json-lossy-check-ip0Qi0MT.js.map → json-lossy-check-CVuRs2hG.js.map} +1 -1
  22. package/dist/_chunks/{live-graph-Dv-JJCZw.js → live-graph-9cSnn_h9.js} +3 -3
  23. package/dist/_chunks/{live-graph-Dv-JJCZw.js.map → live-graph-9cSnn_h9.js.map} +1 -1
  24. package/dist/_chunks/{logger-DiDt5ppH.js → logger-BP0LN6vP.js} +17 -2
  25. package/dist/_chunks/{logger-DiDt5ppH.js.map → logger-BP0LN6vP.js.map} +1 -1
  26. package/dist/_chunks/metadata-routes-DSDjM_hJ.js.map +1 -1
  27. package/dist/_chunks/navigation-root-BQfo1-kG.js.map +1 -1
  28. package/dist/_chunks/{poison-scan-CpeT6_OJ.js → poison-scan-vGV7Re0B.js} +2 -2
  29. package/dist/_chunks/{poison-scan-CpeT6_OJ.js.map → poison-scan-vGV7Re0B.js.map} +1 -1
  30. package/dist/_chunks/{scanner-Bw0oq1HB.js → scanner-DmqdxzbW.js} +392 -7
  31. package/dist/_chunks/scanner-DmqdxzbW.js.map +1 -0
  32. package/dist/_chunks/segment-classify-C539Pa2O.js.map +1 -1
  33. package/dist/_chunks/{sizeof-UwzwB1uM.js → sizeof-BM1409x2.js} +2 -2
  34. package/dist/_chunks/{sizeof-UwzwB1uM.js.map → sizeof-BM1409x2.js.map} +1 -1
  35. package/dist/_chunks/{status-page-marker-gaihi0KZ.js → status-page-marker-BRX9Ib-d.js} +1 -45
  36. package/dist/_chunks/status-page-marker-BRX9Ib-d.js.map +1 -0
  37. package/dist/_chunks/{walkers-BXExhzzk.js → walkers-Czu2jXFq.js} +3 -3
  38. package/dist/_chunks/{walkers-BXExhzzk.js.map → walkers-Czu2jXFq.js.map} +1 -1
  39. package/dist/adapters/cloudflare-kv-cache.js +1 -1
  40. package/dist/analyze/crawl-entry.js +2 -2
  41. package/dist/analyze/graph-command.js +2 -2
  42. package/dist/cache/index.js +2 -2
  43. package/dist/cache/stores/memory.js +1 -1
  44. package/dist/cli.js +3 -3
  45. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -1
  46. package/dist/client/browser-entry/router-init.d.ts.map +1 -1
  47. package/dist/client/error-boundary.js +1 -1
  48. package/dist/client/history.d.ts +0 -9
  49. package/dist/client/history.d.ts.map +1 -1
  50. package/dist/client/index.d.ts +2 -1
  51. package/dist/client/index.d.ts.map +1 -1
  52. package/dist/client/index.js +9 -3
  53. package/dist/client/index.js.map +1 -1
  54. package/dist/client/internal.js +25 -38
  55. package/dist/client/internal.js.map +1 -1
  56. package/dist/client/link.d.ts +22 -0
  57. package/dist/client/link.d.ts.map +1 -1
  58. package/dist/client/navigation-api.d.ts +14 -2
  59. package/dist/client/navigation-api.d.ts.map +1 -1
  60. package/dist/client/navigation-root.d.ts +9 -1
  61. package/dist/client/navigation-root.d.ts.map +1 -1
  62. package/dist/client/navigation-transition.d.ts +6 -1
  63. package/dist/client/navigation-transition.d.ts.map +1 -1
  64. package/dist/client/react-root.d.ts.map +1 -1
  65. package/dist/client/router-effects.d.ts +10 -3
  66. package/dist/client/router-effects.d.ts.map +1 -1
  67. package/dist/client/router-pipeline.d.ts +3 -1
  68. package/dist/client/router-pipeline.d.ts.map +1 -1
  69. package/dist/client/router-types.d.ts +65 -9
  70. package/dist/client/router-types.d.ts.map +1 -1
  71. package/dist/client/router.d.ts.map +1 -1
  72. package/dist/client/segment-cache.d.ts +0 -15
  73. package/dist/client/segment-cache.d.ts.map +1 -1
  74. package/dist/client/use-router.d.ts +13 -6
  75. package/dist/client/use-router.d.ts.map +1 -1
  76. package/dist/config-validation.d.ts +19 -2
  77. package/dist/config-validation.d.ts.map +1 -1
  78. package/dist/index.d.ts.map +1 -1
  79. package/dist/index.js +7 -7
  80. package/dist/index.js.map +1 -1
  81. package/dist/routing/convention-lint.d.ts.map +1 -1
  82. package/dist/routing/export-detect.d.ts +19 -0
  83. package/dist/routing/export-detect.d.ts.map +1 -1
  84. package/dist/routing/index.js +3 -3
  85. package/dist/routing/manifest-codegen.d.ts.map +1 -1
  86. package/dist/routing/scanner.d.ts.map +1 -1
  87. package/dist/routing/types.d.ts +7 -0
  88. package/dist/routing/types.d.ts.map +1 -1
  89. package/dist/server/action-handler.d.ts +1 -1
  90. package/dist/server/action-handler.d.ts.map +1 -1
  91. package/dist/server/actions.d.ts +9 -4
  92. package/dist/server/actions.d.ts.map +1 -1
  93. package/dist/server/csrf.d.ts +38 -19
  94. package/dist/server/csrf.d.ts.map +1 -1
  95. package/dist/server/error-boundary-wrapper.d.ts +8 -4
  96. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  97. package/dist/server/fallback-error.d.ts.map +1 -1
  98. package/dist/server/form-flash.d.ts +1 -1
  99. package/dist/server/index.js +2 -2
  100. package/dist/server/index.js.map +1 -1
  101. package/dist/server/internal.js +249 -16
  102. package/dist/server/internal.js.map +1 -1
  103. package/dist/server/logger.d.ts +16 -3
  104. package/dist/server/logger.d.ts.map +1 -1
  105. package/dist/server/metadata-collector.d.ts +2 -0
  106. package/dist/server/metadata-collector.d.ts.map +1 -1
  107. package/dist/server/metadata-routes.d.ts +12 -1
  108. package/dist/server/metadata-routes.d.ts.map +1 -1
  109. package/dist/server/pipeline-helpers.d.ts +29 -1
  110. package/dist/server/pipeline-helpers.d.ts.map +1 -1
  111. package/dist/server/pipeline.d.ts +8 -1
  112. package/dist/server/pipeline.d.ts.map +1 -1
  113. package/dist/server/route-element-builder.d.ts.map +1 -1
  114. package/dist/server/route-matcher.d.ts +8 -0
  115. package/dist/server/route-matcher.d.ts.map +1 -1
  116. package/dist/server/rsc-entry/{wrap-action-dispatch.d.ts → action-dispatcher.d.ts} +18 -40
  117. package/dist/server/rsc-entry/action-dispatcher.d.ts.map +1 -0
  118. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  119. package/dist/server/safe-load.d.ts +5 -12
  120. package/dist/server/safe-load.d.ts.map +1 -1
  121. package/docs/api/30-api-server.mdx +1 -1
  122. package/docs/api/31-api-client.mdx +23 -20
  123. package/docs/api/34-api-config.mdx +4 -2
  124. package/package.json +1 -1
  125. package/src/client/browser-entry/action-dispatch.ts +28 -28
  126. package/src/client/browser-entry/post-hydration.ts +11 -1
  127. package/src/client/browser-entry/router-init.ts +10 -4
  128. package/src/client/history.ts +0 -22
  129. package/src/client/index.ts +2 -1
  130. package/src/client/link.tsx +30 -1
  131. package/src/client/navigation-api.ts +36 -3
  132. package/src/client/navigation-root.tsx +13 -1
  133. package/src/client/navigation-transition.ts +17 -7
  134. package/src/client/react-root.ts +11 -2
  135. package/src/client/router-effects.ts +11 -4
  136. package/src/client/router-pipeline.ts +4 -0
  137. package/src/client/router-types.ts +80 -6
  138. package/src/client/router.ts +36 -24
  139. package/src/client/segment-cache.ts +0 -65
  140. package/src/client/use-router.ts +25 -6
  141. package/src/config-validation.ts +121 -5
  142. package/src/index.ts +5 -8
  143. package/src/routing/convention-lint.ts +75 -0
  144. package/src/routing/export-detect.ts +88 -0
  145. package/src/routing/manifest-codegen.ts +6 -0
  146. package/src/routing/scanner.ts +9 -0
  147. package/src/routing/types.ts +7 -0
  148. package/src/server/action-handler.ts +14 -11
  149. package/src/server/actions.ts +37 -42
  150. package/src/server/als-registry.ts +1 -1
  151. package/src/server/csrf.ts +100 -72
  152. package/src/server/error-boundary-wrapper.ts +11 -12
  153. package/src/server/fallback-error.ts +13 -21
  154. package/src/server/form-flash.ts +1 -1
  155. package/src/server/logger.ts +19 -3
  156. package/src/server/metadata-collector.ts +4 -1
  157. package/src/server/metadata-routes.ts +23 -8
  158. package/src/server/pipeline-helpers.ts +89 -8
  159. package/src/server/pipeline.ts +27 -2
  160. package/src/server/route-element-builder.ts +1 -0
  161. package/src/server/route-matcher.ts +11 -0
  162. package/src/server/rsc-entry/{wrap-action-dispatch.ts → action-dispatcher.ts} +20 -62
  163. package/src/server/rsc-entry/index.ts +14 -27
  164. package/src/server/safe-load.ts +5 -12
  165. package/dist/_chunks/convention-lint-jKTwKwPe.js.map +0 -1
  166. package/dist/_chunks/dev-server-C4WZdB7L.js.map +0 -1
  167. package/dist/_chunks/file-cache-Dw6BJPG7.js.map +0 -1
  168. package/dist/_chunks/scanner-Bw0oq1HB.js.map +0 -1
  169. package/dist/_chunks/status-page-marker-gaihi0KZ.js.map +0 -1
  170. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +0 -1
@@ -3,9 +3,9 @@ import { n as RENDER_TIMEOUT_CEILING_MS, t as DEFAULT_RENDER_TIMEOUT_MS } from "
3
3
  import { l as registerDevDiscovery } from "./graph-cache-CYiUS2aS.js";
4
4
  import { n as isScannableSourceFile, t as buildSourceExtensions } from "./scan-BoP17W3w.js";
5
5
  import { t as RSC_CONTENT_TYPE } from "./rsc-media-type-DDc7duTD.js";
6
+ import { t as matchUrlParts } from "./tree-match-6yihorhk.js";
6
7
  import { o as isMetadataRouteServePath } from "./metadata-routes-DSDjM_hJ.js";
7
8
  import { r as canonicalize } from "./canonicalize-CgHoscYO.js";
8
- import { t as matchUrlParts } from "./tree-match-6yihorhk.js";
9
9
  import { normalizePath } from "vite";
10
10
  import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
11
11
  import { createRequire } from "node:module";
@@ -961,6 +961,19 @@ function validateConfig(config) {
961
961
  }
962
962
  }
963
963
  }
964
+ if (config.allowedOrigins !== void 0) {
965
+ if (!Array.isArray(config.allowedOrigins)) errors.push({
966
+ field: "allowedOrigins",
967
+ message: "allowedOrigins must be an array of origin strings.",
968
+ value: config.allowedOrigins,
969
+ fatal: true,
970
+ suggestion: "Example: allowedOrigins: [\"https://app.example.com\"]"
971
+ });
972
+ else for (const entry of config.allowedOrigins) {
973
+ const error = allowedOriginError(entry);
974
+ if (error) errors.push(error);
975
+ }
976
+ }
964
977
  if (config.slowRequestMs !== void 0) {
965
978
  if (typeof config.slowRequestMs !== "number" || config.slowRequestMs < 0) errors.push({
966
979
  field: "slowRequestMs",
@@ -1035,24 +1048,101 @@ function validateConfig(config) {
1035
1048
  });
1036
1049
  return errors;
1037
1050
  }
1051
+ /**
1052
+ * Why one `allowedOrigins` entry can never match, or null when it can.
1053
+ *
1054
+ * The CSRF check compares entries to the request's `Origin` header by
1055
+ * exact string, and browsers send only the canonical form — scheme, host,
1056
+ * and non-default port, lowercased, no path. So an entry that is not its
1057
+ * own `new URL(x).origin` (`https://example.com/`, `https://Example.com`,
1058
+ * `example.com`) silently matches nothing. `"null"` is refused outright:
1059
+ * it is the `Origin` of every opaque context at once.
1060
+ */
1061
+ function allowedOriginError(entry) {
1062
+ const field = "allowedOrigins";
1063
+ const fatal = true;
1064
+ if (typeof entry !== "string") return {
1065
+ field,
1066
+ message: `allowedOrigins contains a non-string value: ${JSON.stringify(entry)}.`,
1067
+ value: entry,
1068
+ fatal
1069
+ };
1070
+ if (entry === "null") return {
1071
+ field,
1072
+ message: "allowedOrigins cannot contain \"null\". Browsers send Origin: null from every opaque context — sandboxed iframes (an attacker's <iframe sandbox> included), POSTs redirected across origins, and file: pages — so allowing it allows all of them.",
1073
+ value: entry,
1074
+ suggestion: "To accept a cross-site POST on one endpoint, handle it in a route.ts that exports `const csrf = false` instead.",
1075
+ fatal
1076
+ };
1077
+ if (entry.includes("*")) return {
1078
+ field,
1079
+ message: `allowedOrigins entry ${JSON.stringify(entry)} uses a wildcard. Matching is exact; wildcards are not supported.`,
1080
+ value: entry,
1081
+ suggestion: "List each origin, e.g. [\"https://app.example.com\", \"https://admin.example.com\"].",
1082
+ fatal
1083
+ };
1084
+ const canonical = canonicalOrigin(entry) ?? canonicalOrigin(`https://${entry}`);
1085
+ if (canonical === entry) return null;
1086
+ return {
1087
+ field,
1088
+ message: `allowedOrigins entry ${JSON.stringify(entry)} is not a canonical origin, so it can never match a request's Origin header.`,
1089
+ value: entry,
1090
+ suggestion: canonical ? `Did you mean "${canonical}"? An origin is scheme://host[:port] — lowercase, no path or trailing slash.` : "An origin is scheme://host[:port], e.g. \"https://app.example.com\".",
1091
+ fatal
1092
+ };
1093
+ }
1094
+ /** `new URL(x).origin` for an http(s) URL, or null. Opaque origins are not origins here. */
1095
+ function canonicalOrigin(value) {
1096
+ try {
1097
+ const url = new URL(value);
1098
+ return url.protocol === "http:" || url.protocol === "https:" ? url.origin : null;
1099
+ } catch {
1100
+ return null;
1101
+ }
1102
+ }
1038
1103
  var RED = "\x1B[31m";
1039
1104
  var BOLD = "\x1B[1m";
1040
1105
  var DIM = "\x1B[2m";
1041
1106
  var RESET = "\x1B[0m";
1042
1107
  /**
1043
- * Format config errors for terminal output.
1108
+ * Format config errors for terminal output. Pass `color: false` for text
1109
+ * that goes into a thrown `Error` — escapes there reach CI logs and the
1110
+ * Vite overlay as raw bytes.
1044
1111
  */
1045
- function formatConfigErrors(errors) {
1112
+ function formatConfigErrors(errors, { color = true } = {}) {
1046
1113
  if (errors.length === 0) return "";
1114
+ const [red, bold, dim, reset] = color ? [
1115
+ RED,
1116
+ BOLD,
1117
+ DIM,
1118
+ RESET
1119
+ ] : [
1120
+ "",
1121
+ "",
1122
+ "",
1123
+ ""
1124
+ ];
1047
1125
  const lines = [];
1048
- lines.push(`${RED}${BOLD}[timber]${RESET} ${RED}${errors.length} config error${errors.length !== 1 ? "s" : ""} in timber.config.ts:${RESET}`);
1126
+ lines.push(`${red}${bold}[timber]${reset} ${red}${errors.length} config error${errors.length !== 1 ? "s" : ""} in timber.config.ts:${reset}`);
1049
1127
  for (const err of errors) {
1050
1128
  lines.push("");
1051
- lines.push(` ${RED}✗${RESET} ${BOLD}${err.field}${RESET}: ${err.message}`);
1052
- if (err.suggestion) lines.push(` ${DIM}${err.suggestion}${RESET}`);
1129
+ lines.push(` ${red}✗${reset} ${bold}${err.field}${reset}: ${err.message}`);
1130
+ if (err.suggestion) lines.push(` ${dim}${err.suggestion}${reset}`);
1053
1131
  }
1054
1132
  return lines.join("\n");
1055
1133
  }
1134
+ /**
1135
+ * Surface config errors at startup: non-fatal ones are written to stderr
1136
+ * (Vite may still work partially, and the message guides the fix); fatal
1137
+ * ones then stop startup with a thrown error. Non-fatal errors are written
1138
+ * first so a fatal one does not hide them.
1139
+ */
1140
+ function reportConfigErrors(errors, write = (text) => process.stderr.write(text)) {
1141
+ const warnings = errors.filter((e) => !e.fatal);
1142
+ if (warnings.length > 0) write(`${formatConfigErrors(warnings)}\n\n`);
1143
+ const fatal = errors.filter((e) => e.fatal);
1144
+ if (fatal.length > 0) throw new Error(formatConfigErrors(fatal, { color: false }));
1145
+ }
1056
1146
  var VIRTUAL_MODULE_NAMES = {
1057
1147
  "virtual:timber-rsc-entry": "RSC entry (server component handler)",
1058
1148
  "virtual:timber-ssr-entry": "SSR entry (HTML renderer)",
@@ -1246,7 +1336,7 @@ function createGraphEndpointMiddleware(server, ctx) {
1246
1336
  }
1247
1337
  reflectCors(res, origin);
1248
1338
  try {
1249
- const { classifyLiveFile, classifyLiveProject } = await import("./live-graph-Dv-JJCZw.js");
1339
+ const { classifyLiveFile, classifyLiveProject } = await import("./live-graph-9cSnn_h9.js");
1250
1340
  const preserveSymlinks = server.config.resolve.preserveSymlinks;
1251
1341
  const root = normalizePath(preserveSymlinks ? ctx.root : await realpath(ctx.root));
1252
1342
  const appDir = normalizePath(preserveSymlinks ? ctx.appDir : await realpath(ctx.appDir).catch(() => join(root, relative(ctx.root, ctx.appDir))));
@@ -1944,6 +2034,6 @@ function listenForClientErrors(server, projectRoot) {
1944
2034
  });
1945
2035
  }
1946
2036
  //#endregion
1947
- export { formatMissingPeers as a, formatConfigErrors as i, timberDevServer as n, validateConfig as o, checkPeerDependencies as r, dev_server_exports as t };
2037
+ export { reportConfigErrors as a, formatMissingPeers as i, timberDevServer as n, validateConfig as o, checkPeerDependencies as r, dev_server_exports as t };
1948
2038
 
1949
- //# sourceMappingURL=dev-server-C4WZdB7L.js.map
2039
+ //# sourceMappingURL=dev-server-v97rQH4b.js.map