@absolutejs/absolute 0.20.0-beta.169 → 0.20.0-beta.170

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 (238) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/README.md +232 -0
  3. package/changelog.json +228 -0
  4. package/dist/angular/browser.js +7 -8
  5. package/dist/angular/browser.js.map +6 -5
  6. package/dist/angular/components/core/streamingSlotRegistrar.js +6 -2
  7. package/dist/angular/components/core/streamingSlotRegistry.js +7 -3
  8. package/dist/angular/index.js +555 -156
  9. package/dist/angular/index.js.map +29 -23
  10. package/dist/angular/server.js +555 -156
  11. package/dist/angular/server.js.map +29 -23
  12. package/dist/build/buildWorker.js +14 -8
  13. package/dist/build.js +4949 -1941
  14. package/dist/build.js.map +72 -42
  15. package/dist/cli/{add-7azr0c83.js → add-6a7pjkn9.js} +11 -7
  16. package/dist/cli/{analyze-3cyek6v3.js → analyze-606fshwa.js} +1 -1
  17. package/dist/cli/{build-25rz8v25.js → build-g81xqbb9.js} +1 -1
  18. package/dist/cli/{compile-4jnfxts9.js → compile-9y1w9zpj.js} +3 -3
  19. package/dist/cli/config/server.js +10699 -1538
  20. package/dist/cli/{dev-9tk5hn2e.js → dev-hyeb89hp.js} +5 -1
  21. package/dist/cli/{doctor-4nv2c2j3.js → doctor-h55y9hj1.js} +1 -1
  22. package/dist/cli/{generate-v75p2fct.js → generate-20x1pkf7.js} +4 -4
  23. package/dist/cli/{htmx-427swtdz.js → htmx-6mz2h7k1.js} +2 -2
  24. package/dist/cli/{index-bhbs6d5z.js → index-32ge2w1f.js} +12 -4
  25. package/dist/cli/{index-a4ws2jwd.js → index-3wz3mktm.js} +1 -1
  26. package/dist/cli/{index-b7hjgknf.js → index-9sksd8c8.js} +13 -4
  27. package/dist/cli/{index-eyzwc7gz.js → index-qbrzvmh9.js} +4 -2
  28. package/dist/cli/index-qw98g1p6.js +269 -0
  29. package/dist/cli/{index-434b7j4a.js → index-vtp20gwf.js} +69 -1
  30. package/dist/cli/{index-h7qhz02e.js → index-wk0pyxrg.js} +3 -0
  31. package/dist/cli/{index-k3y8cb6c.js → index-z6f43b20.js} +1 -1
  32. package/dist/cli/index.js +16 -16
  33. package/dist/cli/{islands-8sgky9gh.js → islands-dc54e5y1.js} +1 -1
  34. package/dist/cli/{ls-4m4yqwww.js → ls-b6zz24nt.js} +1 -1
  35. package/dist/cli/{mobile-hcxjr2gf.js → mobile-ajnnvqtv.js} +3 -3
  36. package/dist/cli/prerender-fqpp0m1j.js +10 -0
  37. package/dist/cli/{remove-1ycjx85k.js → remove-t8x1mrxg.js} +4 -4
  38. package/dist/cli/{start-mbaejxhm.js → start-d6p831ny.js} +3 -3
  39. package/dist/cli/{typecheck-dr068pmh.js → typecheck-stbt0qt5.js} +6 -1
  40. package/dist/cli/{workspace-1sycp9g1.js → workspace-61hh6jq1.js} +1 -1
  41. package/dist/client/chunks/index-6b66nzyf.js +381 -0
  42. package/dist/client/chunks/index-6b66nzyf.js.map +11 -0
  43. package/dist/client/chunks/{islands-rc28k5sx.js → islands-s2ta5ajb.js} +5 -2
  44. package/dist/client/chunks/{islands-rc28k5sx.js.map → islands-s2ta5ajb.js.map} +7 -6
  45. package/dist/client/index.js +160 -3
  46. package/dist/client/index.js.map +6 -4
  47. package/dist/client/navigation.js +764 -0
  48. package/dist/client/navigation.js.map +10 -0
  49. package/dist/client/prefetch.js +33 -375
  50. package/dist/client/prefetch.js.map +3 -4
  51. package/dist/core/streamingSlotRegistrar.js +5 -2
  52. package/dist/core/streamingSlotRegistrar.js.map +5 -4
  53. package/dist/core/streamingSlotRegistry.js +5 -2
  54. package/dist/core/streamingSlotRegistry.js.map +5 -4
  55. package/dist/dev/client/cspNonce.ts +28 -0
  56. package/dist/dev/client/handlers/html.ts +4 -3
  57. package/dist/dev/client/handlers/htmx.ts +3 -2
  58. package/dist/dev/client/handlers/svelte.ts +15 -90
  59. package/dist/dev/client/syncDevtools.ts +2 -1
  60. package/dist/dev/serverBootstrap.js +11 -4
  61. package/dist/i18n/index.js +543 -0
  62. package/dist/i18n/index.js.map +15 -0
  63. package/dist/index.js +6339 -2233
  64. package/dist/index.js.map +89 -54
  65. package/dist/islands/index.js +282 -40
  66. package/dist/islands/index.js.map +14 -10
  67. package/dist/mobile/browser.js +7 -2
  68. package/dist/mobile/browser.js.map +5 -4
  69. package/dist/mobile/index.js +7 -2
  70. package/dist/mobile/index.js.map +5 -4
  71. package/dist/mobile/remoteMacAgentEntry.js +1 -1
  72. package/dist/react/components/browser/index.js +94 -4
  73. package/dist/react/components/index.js +150 -10
  74. package/dist/react/components/index.js.map +15 -10
  75. package/dist/react/hooks/index.js +479 -13
  76. package/dist/react/hooks/index.js.map +12 -4
  77. package/dist/react/index.js +769 -166
  78. package/dist/react/index.js.map +32 -21
  79. package/dist/react/router/browser.js +21 -4
  80. package/dist/react/router/browser.js.map +5 -4
  81. package/dist/react/router/index.js +21 -4
  82. package/dist/react/router/index.js.map +5 -4
  83. package/dist/react/server.js +597 -203
  84. package/dist/react/server.js.map +25 -15
  85. package/dist/src/angular/zoneRuntime.d.ts +5 -0
  86. package/dist/src/build/buildReactServerComponents.d.ts +22 -0
  87. package/dist/src/build/downlevelAsyncForZone.d.ts +1 -0
  88. package/dist/src/build/fileRoutes.d.ts +65 -0
  89. package/dist/src/build/fonts/buildFonts.d.ts +25 -0
  90. package/dist/src/build/fonts/fallbackMetrics.d.ts +13 -0
  91. package/dist/src/build/fonts/googleFonts.d.ts +18 -0
  92. package/dist/src/build/fonts/injectFontTags.d.ts +7 -0
  93. package/dist/src/build/fonts/parseFontMetrics.d.ts +4 -0
  94. package/dist/src/build/generateReactIndexes.d.ts +7 -1
  95. package/dist/src/build/htmlIncludes.d.ts +16 -0
  96. package/dist/src/build/inlineSourceMapComment.d.ts +1 -0
  97. package/dist/src/build/scanConventions.d.ts +3 -0
  98. package/dist/src/build/vitals.d.ts +21 -0
  99. package/dist/src/client/formActions.d.ts +29 -0
  100. package/dist/src/client/index.d.ts +2 -0
  101. package/dist/src/client/navigation.d.ts +16 -0
  102. package/dist/src/client/prefetch.d.ts +2 -30
  103. package/dist/src/core/build.d.ts +2 -2
  104. package/dist/src/core/cspNonce.d.ts +12 -0
  105. package/dist/src/core/fileRouteAdapter.d.ts +15 -0
  106. package/dist/src/core/fileRoutes.d.ts +5 -0
  107. package/dist/src/core/formActionFlash.d.ts +25 -0
  108. package/dist/src/core/formActions.d.ts +249 -0
  109. package/dist/src/core/index.d.ts +5 -0
  110. package/dist/src/core/partialPrerender.d.ts +28 -0
  111. package/dist/src/core/partialPrerenderServe.d.ts +24 -0
  112. package/dist/src/core/precompressed.d.ts +11 -1
  113. package/dist/src/core/prerenderNonce.d.ts +9 -0
  114. package/dist/src/core/productionRuntime.d.ts +4 -2
  115. package/dist/src/core/serverOnlyStaticFiles.d.ts +8 -0
  116. package/dist/src/core/staticHtmlNonce.d.ts +2 -0
  117. package/dist/src/core/vitals.d.ts +108 -0
  118. package/dist/src/dev/angular/fastHmrCompiler.d.ts +1 -1
  119. package/dist/src/dev/client/cspNonce.d.ts +2 -0
  120. package/dist/src/dev/fileRouteRefresher.d.ts +5 -0
  121. package/dist/src/dev/importCost/instrument.d.ts +1 -1
  122. package/dist/src/dev/reactServerComponentsRebuild.d.ts +3 -0
  123. package/dist/src/i18n/defineMessages.d.ts +5 -0
  124. package/dist/src/i18n/formatMessage.d.ts +26 -0
  125. package/dist/src/i18n/index.d.ts +6 -0
  126. package/dist/src/i18n/intlCache.d.ts +5 -0
  127. package/dist/src/i18n/routing.d.ts +28 -0
  128. package/dist/src/i18n/translator.d.ts +11 -0
  129. package/dist/src/mobile/androidRelease.d.ts +2 -2
  130. package/dist/src/mobile/iosRelease.d.ts +4 -4
  131. package/dist/src/mobile/materializedBundle.d.ts +1 -1
  132. package/dist/src/mobile/mobileInspect.d.ts +1 -1
  133. package/dist/src/mobile/releaseArtifact.d.ts +2 -2
  134. package/dist/src/mobile/remoteMacProtocol.d.ts +2 -2
  135. package/dist/src/plugins/i18n.d.ts +30 -0
  136. package/dist/src/plugins/index.d.ts +2 -1
  137. package/dist/src/plugins/secureHeaders.d.ts +48 -0
  138. package/dist/src/react/components/Head.d.ts +1 -1
  139. package/dist/src/react/components/StreamSlot.browser.d.ts +1 -0
  140. package/dist/src/react/components/StreamSlot.d.ts +5 -1
  141. package/dist/src/react/components/SuspenseSlot.browser.d.ts +2 -0
  142. package/dist/src/react/components/SuspenseSlot.d.ts +12 -0
  143. package/dist/src/react/fileRoute.d.ts +18 -0
  144. package/dist/src/react/hooks/index.d.ts +4 -0
  145. package/dist/src/react/hooks/useFormAction.d.ts +42 -0
  146. package/dist/src/react/hooks/useI18n.d.ts +15 -0
  147. package/dist/src/react/index.d.ts +2 -0
  148. package/dist/src/react/server.d.ts +2 -0
  149. package/dist/src/react/serverComponents/constants.d.ts +11 -0
  150. package/dist/src/react/serverComponents/flightPayload.d.ts +2 -0
  151. package/dist/src/react/serverComponents/pageHandler.d.ts +14 -0
  152. package/dist/src/svelte/browser.d.ts +1 -0
  153. package/dist/src/svelte/fileRoute.d.ts +15 -0
  154. package/dist/src/svelte/i18n.d.ts +8 -0
  155. package/dist/src/svelte/index.d.ts +2 -0
  156. package/dist/src/svelte/lowerAwaitSlotSyntax.d.ts +5 -1
  157. package/dist/src/svelte/renderToReadableStream.d.ts +10 -2
  158. package/dist/src/svelte/router/browser.d.ts +3 -1
  159. package/dist/src/svelte/router/goto.d.ts +13 -10
  160. package/dist/src/svelte/router/guards.d.ts +43 -0
  161. package/dist/src/svelte/router/index.d.ts +3 -1
  162. package/dist/src/svelte/router/lazy.d.ts +17 -0
  163. package/dist/src/svelte/router/lazyModule.d.ts +29 -0
  164. package/dist/src/svelte/router/navigation.d.ts +55 -0
  165. package/dist/src/svelte/router/pushState.d.ts +4 -2
  166. package/dist/src/svelte/router/scroll.d.ts +34 -0
  167. package/dist/src/svelte/routerSsr.d.ts +9 -0
  168. package/dist/src/svelte/server.d.ts +1 -0
  169. package/dist/src/utils/cspNonceRef.d.ts +8 -0
  170. package/dist/src/utils/fontAssets.d.ts +17 -0
  171. package/dist/src/utils/formActionProtocol.d.ts +10 -0
  172. package/dist/src/utils/generateHeadElement.d.ts +1 -1
  173. package/dist/src/utils/index.d.ts +1 -0
  174. package/dist/src/utils/inlinePageCss.d.ts +18 -0
  175. package/dist/src/utils/loadConfig.d.ts +5 -0
  176. package/dist/src/utils/localeRef.d.ts +10 -0
  177. package/dist/src/utils/resolveConvention.d.ts +6 -1
  178. package/dist/src/utils/streamingSlots.d.ts +5 -0
  179. package/dist/src/vue/browser.d.ts +2 -0
  180. package/dist/src/vue/components/Image.d.ts +2 -2
  181. package/dist/src/vue/index.d.ts +2 -0
  182. package/dist/src/vue/serverDataPayload.d.ts +32 -0
  183. package/dist/src/vue/serverDataState.d.ts +9 -0
  184. package/dist/src/vue/useServerData.browser.d.ts +6 -0
  185. package/dist/src/vue/useServerData.d.ts +24 -0
  186. package/dist/svelte/browser.js +330 -3
  187. package/dist/svelte/browser.js.map +8 -4
  188. package/dist/svelte/components/AwaitSlot.svelte +5 -0
  189. package/dist/svelte/components/Head.svelte +50 -0
  190. package/dist/svelte/components/JsonLd.svelte +9 -1
  191. package/dist/svelte/components/StreamSlot.svelte +5 -0
  192. package/dist/svelte/index.js +1017 -117
  193. package/dist/svelte/index.js.map +38 -24
  194. package/dist/svelte/router/Link.svelte +40 -8
  195. package/dist/svelte/router/Route.svelte +157 -12
  196. package/dist/svelte/router/Route.svelte.d.ts +39 -5
  197. package/dist/svelte/router/Router.svelte +140 -25
  198. package/dist/svelte/router/Router.svelte.d.ts +5 -1
  199. package/dist/svelte/router/browser.ts +10 -0
  200. package/dist/svelte/router/goto.ts +15 -86
  201. package/dist/svelte/router/guards.ts +112 -0
  202. package/dist/svelte/router/index.ts +10 -0
  203. package/dist/svelte/router/lazy.ts +82 -0
  204. package/dist/svelte/router/lazyModule.ts +74 -0
  205. package/dist/svelte/router/navigation.ts +412 -0
  206. package/dist/svelte/router/pushState.ts +7 -4
  207. package/dist/svelte/router/scroll.ts +286 -0
  208. package/dist/svelte/server.js +747 -252
  209. package/dist/svelte/server.js.map +30 -20
  210. package/dist/types/angular.d.ts +2 -0
  211. package/dist/types/build.d.ts +37 -0
  212. package/dist/types/conventions.d.ts +3 -0
  213. package/dist/types/fileRoutes.d.ts +72 -0
  214. package/dist/types/fonts.d.ts +86 -0
  215. package/dist/types/formAction.d.ts +54 -0
  216. package/dist/types/globals.d.ts +10 -0
  217. package/dist/types/i18n.d.ts +185 -0
  218. package/dist/types/index.d.ts +4 -0
  219. package/dist/types/metadata.d.ts +11 -0
  220. package/dist/types/navigation.d.ts +37 -0
  221. package/dist/types/prefetch.d.ts +10 -0
  222. package/dist/types/sitemap.d.ts +4 -0
  223. package/dist/types/svelteRouter.d.ts +89 -2
  224. package/dist/types/svelteRouter.ts +112 -2
  225. package/dist/types/vue.d.ts +46 -1
  226. package/dist/utils/iconVersion.ts +34 -0
  227. package/dist/vue/browser.js +107 -11
  228. package/dist/vue/browser.js.map +7 -4
  229. package/dist/vue/components/index.js +5 -2
  230. package/dist/vue/components/index.js.map +5 -4
  231. package/dist/vue/index.js +712 -158
  232. package/dist/vue/index.js.map +32 -23
  233. package/dist/vue/server.js +310 -79
  234. package/dist/vue/server.js.map +20 -15
  235. package/package.json +9 -1
  236. package/dist/cli/prerender-mfnwsvyt.js +0 -7
  237. package/dist/src/plugins/pageRouter.d.ts +0 -1
  238. /package/dist/cli/{index-j7m8pq48.js → index-rervww4p.js} +0 -0
@@ -35,7 +35,10 @@ import {
35
35
  } from "./index-71gchbzt.js";
36
36
  import {
37
37
  loadConfig
38
- } from "./index-h7qhz02e.js";
38
+ } from "./index-wk0pyxrg.js";
39
+ import {
40
+ ensureFileRouteModule
41
+ } from "./index-qw98g1p6.js";
39
42
  import {
40
43
  TUNNEL_CONTROL_PATH,
41
44
  TUNNEL_FORWARDED_HOST_HEADER,
@@ -2467,6 +2470,7 @@ var dev = async (serverEntry, configPath, options = {}) => {
2467
2470
  } catch {
2468
2471
  return;
2469
2472
  }
2473
+ ensureFileRouteModule(cfg);
2470
2474
  const refreshedDevConfig = resolveDevConfig(cfg?.dev);
2471
2475
  if (options.androidDevice && ["localhost", "127.0.0.1", "::1"].includes(refreshedDevConfig.host)) {
2472
2476
  refreshedDevConfig.host = "0.0.0.0";
@@ -4,7 +4,7 @@ import {
4
4
  } from "./index-fgz435qn.js";
5
5
  import {
6
6
  loadRawConfig
7
- } from "./index-h7qhz02e.js";
7
+ } from "./index-wk0pyxrg.js";
8
8
  import {
9
9
  colors
10
10
  } from "./index-xw1byvzp.js";
@@ -1,15 +1,15 @@
1
1
  // @bun
2
- import"./index-h7qhz02e.js";
2
+ import"./index-wk0pyxrg.js";
3
3
  import {
4
4
  frameworks,
5
5
  resolveProject,
6
6
  selectFramework,
7
7
  toModuleSpecifier
8
- } from "./index-eyzwc7gz.js";
8
+ } from "./index-qbrzvmh9.js";
9
9
  import"./index-fgz435qn.js";
10
10
  import {
11
11
  wirePluginUse
12
- } from "./index-a4ws2jwd.js";
12
+ } from "./index-3wz3mktm.js";
13
13
  import {
14
14
  isValidName,
15
15
  toCamelCase,
@@ -18,7 +18,7 @@ import {
18
18
  toTitleCase,
19
19
  emptyOutcome,
20
20
  generatePage
21
- } from "./index-b7hjgknf.js";
21
+ } from "./index-9sksd8c8.js";
22
22
  import {
23
23
  colors
24
24
  } from "./index-xw1byvzp.js";
@@ -1,8 +1,8 @@
1
1
  // @bun
2
- import"./index-h7qhz02e.js";
2
+ import"./index-wk0pyxrg.js";
3
3
  import {
4
4
  resolveProject
5
- } from "./index-eyzwc7gz.js";
5
+ } from "./index-qbrzvmh9.js";
6
6
  import"./index-fgz435qn.js";
7
7
  import {
8
8
  colors
@@ -20,7 +20,7 @@ import {
20
20
  createElysiaOpenApiTypeboxPlugin,
21
21
  createOptionalPeerPlugin,
22
22
  resolveServerBundleExternals
23
- } from "./index-j7m8pq48.js";
23
+ } from "./index-rervww4p.js";
24
24
  import {
25
25
  normalizeAbsoluteMobileConfig2
26
26
  } from "./index-t7yf3vxs.js";
@@ -29,7 +29,7 @@ import {
29
29
  } from "./index-pch0v1z6.js";
30
30
  import {
31
31
  loadConfig
32
- } from "./index-h7qhz02e.js";
32
+ } from "./index-wk0pyxrg.js";
33
33
  import {
34
34
  stripStringsAndComments
35
35
  } from "./index-prs14ys9.js";
@@ -76,6 +76,7 @@ var RUNTIME_KEYS = [
76
76
  "static",
77
77
  "svelteDirectory",
78
78
  "telemetry",
79
+ "vitals",
79
80
  "vueDirectory"
80
81
  ];
81
82
  var productionRuntimeConfigOf = (config) => {
@@ -83,6 +84,8 @@ var productionRuntimeConfigOf = (config) => {
83
84
  for (const key of RUNTIME_KEYS)
84
85
  if (config[key] !== undefined)
85
86
  picked[key] = config[key];
87
+ if (config.angular?.changeDetection)
88
+ picked.angular = { changeDetection: config.angular.changeDetection };
86
89
  const runtime = JSON.parse(JSON.stringify(picked));
87
90
  return runtime;
88
91
  };
@@ -178,7 +181,7 @@ var jsxDevRuntimeCompatPath = resolveJsxDevRuntimeCompatPath();
178
181
  var prerenderStaticPages = async (outputPath, prerenderPort, resolvedOutdir, staticConfig, absoluteVersion, configPath) => {
179
182
  const prerenderStart = performance.now();
180
183
  process.stdout.write(cliTag("\x1B[36m", "Pre-rendering static pages"));
181
- const { prerenderWithServer } = await import("./prerender-mfnwsvyt.js");
184
+ const { prerenderWithServer } = await import("./prerender-fqpp0m1j.js");
182
185
  try {
183
186
  killStaleProcesses(prerenderPort);
184
187
  const result = await prerenderWithServer(outputPath, prerenderPort, resolvedOutdir, staticConfig, {
@@ -436,10 +439,14 @@ var start2 = async (serverEntry, outdir, configPath, options = {}) => {
436
439
  };
437
440
  const islandRegistrySpec = buildConfig.islands?.registry;
438
441
  const islandRegistryPlugin = islandRegistrySpec ? createIslandRegistryDefinitionPlugin(await loadIslandRegistryBuildInfo(resolve(islandRegistrySpec))) : undefined;
442
+ const sharedPageRuntimes = buildConfig.svelteDirectory ? ["svelte", "svelte/*"] : [];
439
443
  const serverBundle = await Bun.build({
440
444
  define: { "process.env.NODE_ENV": '"production"' },
441
445
  entrypoints: [resolve(serverEntry)],
442
- external: resolveServerBundleExternals(buildConfig),
446
+ external: [
447
+ ...resolveServerBundleExternals(buildConfig),
448
+ ...sharedPageRuntimes
449
+ ],
443
450
  outdir: resolvedOutdir,
444
451
  plugins: [
445
452
  createOptionalPeerPlugin(),
@@ -453,6 +460,7 @@ var start2 = async (serverEntry, outdir, configPath, options = {}) => {
453
460
  stubPlugin,
454
461
  createBunStringRawUnicodePlugin()
455
462
  ],
463
+ sourcemap: "linked",
456
464
  target: "bun",
457
465
  throw: false
458
466
  });
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  toModuleSpecifier
4
- } from "./index-eyzwc7gz.js";
4
+ } from "./index-qbrzvmh9.js";
5
5
 
6
6
  // src/cli/generate/routeWiring.ts
7
7
  import ts from "typescript";
@@ -3,11 +3,11 @@ import {
3
3
  frameworks,
4
4
  sharedDirFor,
5
5
  toModuleSpecifier
6
- } from "./index-eyzwc7gz.js";
6
+ } from "./index-qbrzvmh9.js";
7
7
  import {
8
8
  findRoutingFile,
9
9
  wireRoute
10
- } from "./index-a4ws2jwd.js";
10
+ } from "./index-3wz3mktm.js";
11
11
 
12
12
  // src/cli/generate/naming.ts
13
13
  var tokenize = (raw) => raw.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").split(/[^a-zA-Z0-9]+/).filter((token) => token.length > 0).map((token) => token.toLowerCase());
@@ -314,13 +314,22 @@ var vuePage = (ctx) => `<script setup lang="ts">
314
314
  </main>
315
315
  </template>
316
316
  `;
317
+ var angularNavItems = (items) => items.length === 0 ? "[]" : `[
318
+ ${items.map((item) => ` { href: ${JSON.stringify(item.href)}, label: ${JSON.stringify(item.label)} }`).join(`,
319
+ `)}
320
+ ]`;
317
321
  var angularPage = (ctx) => `import { Component } from '@angular/core';
318
- import { navData } from '${ctx.navImportPath}';
319
322
 
320
323
  // This page has no per-request DI context, so the SSR handler's
321
324
  // \`requestContext\` is an empty object.
322
325
  export type Context = Record<string, never>;
323
326
 
327
+ type NavItem = { href: string; label: string };
328
+
329
+ // The site's pages when this one was generated. Edit freely; generating
330
+ // another page doesn't rewrite this list.
331
+ const navItems: NavItem[] = ${angularNavItems(ctx.navItems)};
332
+
324
333
  @Component({
325
334
  imports: [],
326
335
  selector: '${ctx.kebab}-page',
@@ -337,7 +346,7 @@ export type Context = Record<string, never>;
337
346
  \`
338
347
  })
339
348
  export class ${ctx.pascal}Component {
340
- navItems = navData;
349
+ navItems = navItems;
341
350
  }
342
351
  `;
343
352
  var htmlHead = (ctx, extraHead) => `<!doctype html>
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  loadConfig
4
- } from "./index-h7qhz02e.js";
4
+ } from "./index-wk0pyxrg.js";
5
5
  import {
6
6
  isRecord
7
7
  } from "./index-tx0kx9zx.js";
@@ -419,7 +419,9 @@ var findConfigObject = (sourceFile) => {
419
419
  if (ts2.isExportAssignment(node) && ts2.isObjectLiteralExpression(node.expression)) {
420
420
  return node.expression;
421
421
  }
422
- node.forEachChild((child) => pending.push(child));
422
+ node.forEachChild((child) => {
423
+ pending.push(child);
424
+ });
423
425
  }
424
426
  return null;
425
427
  };
@@ -0,0 +1,269 @@
1
+ // @bun
2
+ // src/build/fileRoutes.ts
3
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
4
+ import {
5
+ dirname,
6
+ extname,
7
+ isAbsolute,
8
+ join,
9
+ relative,
10
+ resolve,
11
+ sep
12
+ } from "path";
13
+ var {Glob } = globalThis.Bun;
14
+ var DEFAULT_DIRECTORY = "routes";
15
+ var DEFAULT_OUTPUT = join("src", "routes.gen.ts");
16
+ var HASH_LENGTH = 6;
17
+ var HASH_RADIX = 36;
18
+ var PAGE_GLOBS = {
19
+ react: "**/*.{tsx,jsx}",
20
+ svelte: "**/*.svelte"
21
+ };
22
+ var PAGE_EXTENSIONS = {
23
+ react: [".tsx", ".jsx"],
24
+ svelte: [".svelte"]
25
+ };
26
+ var SERVER_EXTENSIONS = [".server.ts", ".server.js"];
27
+ var CONVENTION_RE = /^(?:.+\.)?(?:error|loading|not-found)\.[^.]+$/;
28
+ var TEST_RE = /\.(?:test|spec)\.[^.]+$/;
29
+ var PARAM_RE = /^\[([A-Za-z_$][\w$]*)\]$/;
30
+ var STATIC_SEGMENT_RE = /^[A-Za-z0-9._~-]+$/;
31
+ var REGISTRY_KEY = Symbol.for("absolutejs.fileRoutes.registry");
32
+ var isRegistry = (value) => typeof value === "object" && value !== null && ("bySource" in value) && value.bySource instanceof Map && ("roots" in value) && Array.isArray(value.roots);
33
+ var registry = () => {
34
+ const existing = Reflect.get(globalThis, REGISTRY_KEY);
35
+ if (isRegistry(existing))
36
+ return existing;
37
+ const created = { bySource: new Map, roots: [] };
38
+ Reflect.set(globalThis, REGISTRY_KEY, created);
39
+ return created;
40
+ };
41
+ var toPosix = (path) => path.split(sep).join("/");
42
+ var optionsOf = (config) => {
43
+ const { fileRoutes } = config;
44
+ if (!fileRoutes)
45
+ return;
46
+ const options = fileRoutes === true ? {} : fileRoutes;
47
+ return options;
48
+ };
49
+ var resolveFileRoutes = (config, root = process.cwd()) => {
50
+ const options = optionsOf(config);
51
+ if (!options)
52
+ return;
53
+ const directory = options.directory ?? DEFAULT_DIRECTORY;
54
+ const roots = [];
55
+ if (config.reactDirectory)
56
+ roots.push({
57
+ dir: resolve(root, config.reactDirectory, directory),
58
+ framework: "react"
59
+ });
60
+ if (config.svelteDirectory)
61
+ roots.push({
62
+ dir: resolve(root, config.svelteDirectory, directory),
63
+ framework: "svelte"
64
+ });
65
+ const resolved = {
66
+ output: resolve(root, options.output ?? DEFAULT_OUTPUT),
67
+ roots
68
+ };
69
+ return resolved;
70
+ };
71
+ var pageExtensionOf = (framework, file) => PAGE_EXTENSIONS[framework].find((extension) => file.endsWith(extension));
72
+ var isIgnoredSegment = (segment) => segment.startsWith("_") || segment.startsWith(".");
73
+ var isRouteCandidate = (relativePath) => {
74
+ const segments = relativePath.split("/");
75
+ const fileName = segments[segments.length - 1] ?? "";
76
+ return !segments.some(isIgnoredSegment) && !CONVENTION_RE.test(fileName) && !TEST_RE.test(fileName) && !fileName.includes(".server.");
77
+ };
78
+ var segmentToPath = (segment) => {
79
+ const param = PARAM_RE.exec(segment);
80
+ if (param)
81
+ return { path: `:${param[1]}` };
82
+ if (segment.startsWith("[") || segment.startsWith("(")) {
83
+ return {
84
+ error: `"${segment}" is not supported yet \u2014 only static segments and [param] segments are (catch-all, optional and group segments come later).`
85
+ };
86
+ }
87
+ if (!STATIC_SEGMENT_RE.test(segment)) {
88
+ return {
89
+ error: `"${segment}" has characters a URL path segment cannot hold unescaped.`
90
+ };
91
+ }
92
+ return { path: segment };
93
+ };
94
+ var stripPageExtension = (framework, relativePath) => {
95
+ const extension = pageExtensionOf(framework, relativePath) ?? "";
96
+ return relativePath.slice(0, relativePath.length - extension.length);
97
+ };
98
+ var fileRoutePath = (framework, relativePath) => {
99
+ const segments = stripPageExtension(framework, relativePath).split("/");
100
+ const last = segments[segments.length - 1];
101
+ const routeSegments = last === "index" ? segments.slice(0, -1) : segments;
102
+ const parts = [];
103
+ for (const segment of routeSegments) {
104
+ const result = segmentToPath(segment);
105
+ if ("error" in result)
106
+ return result;
107
+ parts.push(result.path);
108
+ }
109
+ return { path: `/${parts.join("/")}` };
110
+ };
111
+ var pascalSegment = (segment) => {
112
+ const words = segment.split(/[^A-Za-z0-9]+/).filter(Boolean);
113
+ return words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
114
+ };
115
+ var fileRoutePageName = (framework, relativePath) => {
116
+ const stem = stripPageExtension(framework, relativePath);
117
+ const readable = stem.split("/").map(pascalSegment).join("");
118
+ const hash = Bun.hash(`${framework}:${stem}`).toString(HASH_RADIX).slice(-HASH_LENGTH).padStart(HASH_LENGTH, "0");
119
+ return `Route${readable}${hash}`;
120
+ };
121
+ var findServerModule = (framework, source) => {
122
+ const extension = pageExtensionOf(framework, source) ?? extname(source);
123
+ const stem = source.slice(0, source.length - extension.length);
124
+ return SERVER_EXTENSIONS.map((suffix) => `${stem}${suffix}`).find((candidate) => existsSync(candidate));
125
+ };
126
+ var routeFromFile = (root, relativePath, problems) => {
127
+ const source = join(root.dir, relativePath);
128
+ const mapped = fileRoutePath(root.framework, relativePath);
129
+ if ("error" in mapped) {
130
+ problems.push(`${toPosix(relative(process.cwd(), source))}: ${mapped.error}`);
131
+ return;
132
+ }
133
+ const route = {
134
+ framework: root.framework,
135
+ name: fileRoutePageName(root.framework, relativePath),
136
+ path: mapped.path,
137
+ server: findServerModule(root.framework, source),
138
+ source
139
+ };
140
+ return route;
141
+ };
142
+ var scanRoot = (root, problems) => {
143
+ if (!existsSync(root.dir))
144
+ return [];
145
+ const glob = new Glob(PAGE_GLOBS[root.framework]);
146
+ const files = [...glob.scanSync({ cwd: root.dir })].map(toPosix).filter(isRouteCandidate).sort();
147
+ return files.map((file) => routeFromFile(root, file, problems)).filter((route) => route !== undefined);
148
+ };
149
+ var conflictMessage = (route, existing) => `${toPosix(relative(process.cwd(), route.source))} and ${toPosix(relative(process.cwd(), existing.source))} both serve ${route.path}; keep one.`;
150
+ var reportConflicts = (routes, problems) => {
151
+ const byPath = new Map;
152
+ for (const route of routes) {
153
+ const existing = byPath.get(route.path);
154
+ if (existing)
155
+ problems.push(conflictMessage(route, existing));
156
+ else
157
+ byPath.set(route.path, route);
158
+ }
159
+ return [...byPath.values()];
160
+ };
161
+ var compareRoutes = (left, right) => left.path.localeCompare(right.path) || left.framework.localeCompare(right.framework);
162
+ var remember = (roots, routes) => {
163
+ const state = registry();
164
+ state.roots = roots;
165
+ state.bySource = new Map(routes.map((route) => [route.source, route]));
166
+ };
167
+ var scanFileRoutes = (config) => {
168
+ const resolved = resolveFileRoutes(config);
169
+ const problems = [];
170
+ if (!resolved) {
171
+ remember([], []);
172
+ const empty = { problems, routes: [] };
173
+ return empty;
174
+ }
175
+ const scanned = resolved.roots.flatMap((root) => scanRoot(root, problems));
176
+ const routes = reportConflicts(scanned, problems).sort(compareRoutes);
177
+ remember(resolved.roots, routes);
178
+ const scan = { problems, routes };
179
+ return scan;
180
+ };
181
+ var quote = (value) => `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
182
+ var importSpecifier = (outputDir, target) => {
183
+ const extension = extname(target);
184
+ const keepsExtension = extension === ".svelte";
185
+ const withoutExtension = keepsExtension ? target : target.slice(0, target.length - extension.length);
186
+ const path = toPosix(relative(outputDir, withoutExtension));
187
+ return path.startsWith(".") ? path : `./${path}`;
188
+ };
189
+ var ADAPTERS = {
190
+ react: {
191
+ name: "reactFileRoute",
192
+ specifier: "@absolutejs/absolute/react/server"
193
+ },
194
+ svelte: {
195
+ name: "svelteFileRoute",
196
+ specifier: "@absolutejs/absolute/svelte/server"
197
+ }
198
+ };
199
+ var renderRoute = (route, outputDir) => {
200
+ const page = quote(importSpecifier(outputDir, route.source));
201
+ const server = route.server ? quote(importSpecifier(outputDir, route.server)) : undefined;
202
+ const serverType = server ? `typeof import(${server})` : "undefined";
203
+ const source = quote(toPosix(relative(process.cwd(), route.source)));
204
+ const lines = [
205
+ ` ${ADAPTERS[route.framework].name}<`,
206
+ ` ${quote(route.path)},`,
207
+ ` typeof import(${page}),`,
208
+ ` ${serverType}`,
209
+ ` >({`,
210
+ ` name: ${quote(route.name)},`,
211
+ ...route.framework === "react" ? [` page: () => import(${page}),`] : [],
212
+ ` path: ${quote(route.path)},`,
213
+ ...server ? [` server: () => import(${server}),`] : [],
214
+ ` source: ${source}`,
215
+ ` })`
216
+ ];
217
+ return lines.join(`
218
+ `);
219
+ };
220
+ var renderFileRouteModule = (routes, output) => {
221
+ const outputDir = dirname(output);
222
+ const frameworks = [...new Set(routes.map((route) => route.framework))].sort().map((framework) => ADAPTERS[framework]);
223
+ const imports = [
224
+ `import type { FileRouteDefinition } from '@absolutejs/absolute';`,
225
+ ...frameworks.map((adapter) => `import { ${adapter.name} } from '${adapter.specifier}';`)
226
+ ];
227
+ const body = routes.length === 0 ? "export const routeTree: readonly FileRouteDefinition[] = [];" : [
228
+ "export const routeTree: readonly FileRouteDefinition[] = [",
229
+ routes.map((route) => renderRoute(route, outputDir)).join(`,
230
+ `),
231
+ "];"
232
+ ].join(`
233
+ `);
234
+ return [
235
+ "// Generated by AbsoluteJS from your route files (`fileRoutes` in",
236
+ "// absolute.config.ts). Do not edit: it is rewritten whenever a route",
237
+ "// file is added, renamed or removed.",
238
+ ...imports,
239
+ "",
240
+ body,
241
+ ""
242
+ ].join(`
243
+ `);
244
+ };
245
+ var writeIfChanged = (path, contents) => {
246
+ const current = existsSync(path) ? readFileSync(path, "utf-8") : undefined;
247
+ if (current === contents)
248
+ return false;
249
+ mkdirSync(dirname(path), { recursive: true });
250
+ writeFileSync(path, contents);
251
+ return true;
252
+ };
253
+ var ensureFileRouteModule = (config) => {
254
+ try {
255
+ syncFileRoutes(config);
256
+ } catch {}
257
+ };
258
+ var syncFileRoutes = (config) => {
259
+ const resolved = resolveFileRoutes(config);
260
+ if (!resolved) {
261
+ remember([], []);
262
+ return;
263
+ }
264
+ const scan = scanFileRoutes(config);
265
+ const written = writeIfChanged(resolved.output, renderFileRouteModule(scan.routes, resolved.output));
266
+ return { ...scan, output: resolved.output, written };
267
+ };
268
+
269
+ export { ensureFileRouteModule };
@@ -2,6 +2,70 @@
2
2
  // src/core/prerender.ts
3
3
  import { mkdirSync, readFileSync } from "fs";
4
4
  import { join } from "path";
5
+
6
+ // src/core/partialPrerender.ts
7
+ import { rm } from "fs/promises";
8
+ var PARTIAL_HOLES_HEADER = "X-Absolute-Partial-Holes";
9
+ var PARTIAL_SHELL_HEADER = "X-Absolute-Partial-Shell";
10
+ var SINK_STORAGE_KEY = Symbol.for("absolutejs.partialPrerenderHolesSink");
11
+ var decodePartialHoles = (value) => value ? value.split(",").filter(Boolean).map((id) => decodeURIComponent(id)) : [];
12
+ var encodePartialHoles = (ids) => ids.map((id) => encodeURIComponent(id)).join(",");
13
+ var holesPath = (htmlPath) => htmlPath.replace(/\.html$/, ".holes");
14
+ var writePartialHoles = async (htmlPath, response) => {
15
+ const ids = decodePartialHoles(response.headers.get(PARTIAL_HOLES_HEADER));
16
+ if (ids.length > 0) {
17
+ await Bun.write(holesPath(htmlPath), `${encodePartialHoles(ids).split(",").join(`
18
+ `)}
19
+ `);
20
+ } else {
21
+ await rm(holesPath(htmlPath), { force: true });
22
+ }
23
+ return ids;
24
+ };
25
+
26
+ // src/core/prerenderNonce.ts
27
+ import { rm as rm2 } from "fs/promises";
28
+
29
+ // src/utils/logger.ts
30
+ var colors = {
31
+ blue: "\x1B[34m",
32
+ bold: "\x1B[1m",
33
+ cyan: "\x1B[36m",
34
+ dim: "\x1B[2m",
35
+ green: "\x1B[32m",
36
+ magenta: "\x1B[35m",
37
+ red: "\x1B[31m",
38
+ reset: "\x1B[0m",
39
+ white: "\x1B[37m",
40
+ yellow: "\x1B[33m"
41
+ };
42
+ var frameworkColors = {
43
+ angular: colors.magenta,
44
+ assets: colors.dim,
45
+ css: colors.cyan,
46
+ html: colors.white,
47
+ htmx: colors.white,
48
+ react: colors.blue,
49
+ svelte: colors.yellow,
50
+ vue: colors.green
51
+ };
52
+
53
+ // src/core/prerenderNonce.ts
54
+ var CSP_HEADERS = [
55
+ "content-security-policy",
56
+ "content-security-policy-report-only"
57
+ ];
58
+ var noncePath = (htmlPath) => htmlPath.replace(/\.html$/, ".nonce");
59
+ var renderedNonce = (response) => CSP_HEADERS.map((name) => response.headers.get(name)).map((policy) => policy?.match(/'nonce-([^']+)'/)?.[1]).find((nonce) => nonce !== undefined);
60
+ var writeRenderedNonce = async (htmlPath, nonce) => {
61
+ if (nonce)
62
+ await Bun.write(noncePath(htmlPath), nonce);
63
+ else
64
+ await rm2(noncePath(htmlPath), { force: true });
65
+ };
66
+ var warned = new Set;
67
+
68
+ // src/core/prerender.ts
5
69
  var SERVER_OUTPUT_LIMIT = 4000;
6
70
  var STARTUP_POLL_INTERVAL_MS = 100;
7
71
  var DEFAULT_STARTUP_TIMEOUT_MS = 30000;
@@ -62,6 +126,7 @@ var crawlRoutes = async (baseUrl) => {
62
126
  };
63
127
  var prerenderRoute = async (baseUrl, route, prerenderDir, result, log) => {
64
128
  const res = await fetchWithTimeout(`${baseUrl}${route}`, {
129
+ headers: { [PARTIAL_SHELL_HEADER]: "1" },
65
130
  redirect: "manual"
66
131
  }).catch(() => null);
67
132
  if (!res) {
@@ -85,9 +150,12 @@ var prerenderRoute = async (baseUrl, route, prerenderDir, result, log) => {
85
150
  const fileName = routeToFilename(route);
86
151
  const filePath = join(prerenderDir, fileName);
87
152
  await Bun.write(filePath, html);
153
+ await writeRenderedNonce(filePath, renderedNonce(res));
154
+ const holes = await writePartialHoles(filePath, res);
88
155
  await writeTimestamp(filePath);
89
156
  result.routes.set(route, filePath);
90
- log?.(` Pre-rendered ${route} \u2192 ${fileName} (${html.length} bytes)`);
157
+ const partial = holes.length > 0 ? `, partial: ${holes.length} dynamic slot${holes.length === 1 ? "" : "s"}` : "";
158
+ log?.(` Pre-rendered ${route} \u2192 ${fileName} (${html.length} bytes${partial})`);
91
159
  };
92
160
  var prerender = async (port, outDir, staticConfig, log) => {
93
161
  const prerenderDir = join(outDir, "_prerendered");
@@ -14,8 +14,10 @@ var RESERVED_TOP_LEVEL_KEYS = new Set([
14
14
  "emberDirectory",
15
15
  "entry",
16
16
  "env",
17
+ "fileRoutes",
17
18
  "htmlDirectory",
18
19
  "htmxDirectory",
20
+ "fonts",
19
21
  "images",
20
22
  "incrementalFiles",
21
23
  "islands",
@@ -34,6 +36,7 @@ var RESERVED_TOP_LEVEL_KEYS = new Set([
34
36
  "tailwind",
35
37
  "ready",
36
38
  "visibility",
39
+ "vitals",
37
40
  "vueDirectory"
38
41
  ]);
39
42
  var isObject = (value) => typeof value === "object" && value !== null;
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  findConfigObject
4
- } from "./index-eyzwc7gz.js";
4
+ } from "./index-qbrzvmh9.js";
5
5
  import {
6
6
  isRecord
7
7
  } from "./index-tx0kx9zx.js";