@absolutejs/absolute 0.19.0-beta.966 → 0.19.0-beta.968

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 (43) hide show
  1. package/dist/angular/browser.js +24 -20
  2. package/dist/angular/browser.js.map +5 -4
  3. package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
  4. package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
  5. package/dist/angular/index.js +214 -185
  6. package/dist/angular/index.js.map +10 -8
  7. package/dist/angular/server.js +197 -172
  8. package/dist/angular/server.js.map +8 -7
  9. package/dist/build.js +1429 -1019
  10. package/dist/build.js.map +10 -6
  11. package/dist/client/index.js +17 -43
  12. package/dist/client/index.js.map +4 -5
  13. package/dist/index.js +1481 -1071
  14. package/dist/index.js.map +11 -7
  15. package/dist/islands/index.js +17 -43
  16. package/dist/islands/index.js.map +4 -5
  17. package/dist/react/index.js +18 -36
  18. package/dist/react/index.js.map +3 -3
  19. package/dist/react/server.js +2 -2
  20. package/dist/react/server.js.map +2 -2
  21. package/dist/src/angular/browser.d.ts +1 -2
  22. package/dist/src/angular/composables/index.d.ts +1 -0
  23. package/dist/src/angular/composables/usePageContext.d.ts +16 -0
  24. package/dist/src/angular/index.d.ts +1 -2
  25. package/dist/src/angular/loadRouteMounts.d.ts +3 -0
  26. package/dist/src/angular/pageHandler.d.ts +18 -12
  27. package/dist/src/angular/server.d.ts +0 -1
  28. package/dist/src/angular/ssrRender.d.ts +2 -6
  29. package/dist/src/build/emitAngularProvidersFiles.d.ts +18 -0
  30. package/dist/src/build/emitAngularRouteMounts.d.ts +3 -0
  31. package/dist/src/build/runAngularHandlerScan.d.ts +10 -0
  32. package/dist/src/build/scanAngularHandlerCalls.d.ts +35 -0
  33. package/dist/svelte/index.js +18 -36
  34. package/dist/svelte/index.js.map +3 -3
  35. package/dist/svelte/server.js +2 -2
  36. package/dist/svelte/server.js.map +2 -2
  37. package/dist/types/angular.d.ts +15 -46
  38. package/dist/types/ember.d.ts +1 -3
  39. package/dist/vue/index.js +18 -36
  40. package/dist/vue/index.js.map +3 -3
  41. package/dist/vue/server.js +2 -2
  42. package/dist/vue/server.js.map +2 -2
  43. package/package.json +1 -1
@@ -174,7 +174,7 @@ var normalizeSlug = (str) => str.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-
174
174
  return str.charAt(0).toUpperCase() + str.slice(1);
175
175
  }
176
176
  return normalizeSlug(str).split(/[-_]/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase()).join("");
177
- }, toScreamingSnake = (str) => str.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toUpperCase();
177
+ };
178
178
 
179
179
  // src/utils/registerClientScript.ts
180
180
  var scriptRegistry, requestCounter = 0, getRequestId = () => `req_${Date.now()}_${++requestCounter}`, ssrContextGetter = null, getSsrContextId = () => ssrContextGetter?.() || Object.getOwnPropertyDescriptor(globalThis, "__absolutejs_requestId")?.value, registerClientScript = (script, requestId) => {
@@ -512,37 +512,19 @@ var buildRequestProviders = (deps, request, requestContext, responseInit) => [
512
512
  ];
513
513
 
514
514
  // src/angular/ssrRender.ts
515
- var routePropsCache, cacheRouteData = (pagePath, data) => {
515
+ var routeContextCache, cacheRouteData = (pagePath, data) => {
516
516
  const cacheKey = pagePath.split("?")[0] ?? pagePath;
517
- routePropsCache.set(cacheKey, data);
518
- }, getCachedRouteData = (pagePath) => routePropsCache.get(pagePath), selectorCache, buildProviders = (deps, sanitizer, maybeProps, tokenMap, request, requestContext, responseInit, userProviders = []) => {
519
- const providers = [
520
- deps.provideServerRendering(),
521
- deps.provideClientHydration(deps.withHttpTransferCacheOptions(buildAbsoluteHttpTransferCacheOptions())),
522
- deps.provideZonelessChangeDetection(),
523
- { provide: deps.APP_BASE_HREF, useValue: "/" },
524
- {
525
- provide: deps.DomSanitizer,
526
- useValue: sanitizer
527
- },
528
- { provide: deps.Sanitizer, useValue: sanitizer },
529
- ...buildRequestProviders(deps, request, requestContext, responseInit),
530
- ...userProviders
531
- ];
532
- if (!maybeProps) {
533
- return providers;
534
- }
535
- const propProviders = Object.entries(maybeProps).map(([propName, propValue]) => ({
536
- token: tokenMap.get(toScreamingSnake(propName)),
537
- value: propValue
538
- })).filter((entry) => entry.token).map((entry) => ({ provide: entry.token, useValue: entry.value }));
539
- return [...providers, ...propProviders];
540
- }, isInjectionToken = (value) => {
541
- if (!value || typeof value !== "object") {
542
- return false;
543
- }
544
- return "ngMetadataName" in value && value.ngMetadataName === "InjectionToken";
545
- }, discoverTokens = (pageModule) => new Map(Object.entries(pageModule).filter(([, value]) => isInjectionToken(value))), resolveSelector = (deps, pagePath, PageComponent) => {
517
+ routeContextCache.set(cacheKey, data);
518
+ }, getCachedRouteData = (pagePath) => routeContextCache.get(pagePath), selectorCache, buildProviders = (deps, sanitizer, request, requestContext, responseInit, userProviders = []) => [
519
+ deps.provideServerRendering(),
520
+ deps.provideClientHydration(deps.withHttpTransferCacheOptions(buildAbsoluteHttpTransferCacheOptions())),
521
+ deps.provideZonelessChangeDetection(),
522
+ { provide: deps.APP_BASE_HREF, useValue: "/" },
523
+ { provide: deps.DomSanitizer, useValue: sanitizer },
524
+ { provide: deps.Sanitizer, useValue: sanitizer },
525
+ ...buildRequestProviders(deps, request, requestContext, responseInit),
526
+ ...userProviders
527
+ ], resolveSelector = (deps, pagePath, PageComponent) => {
546
528
  const cached = selectorCache.get(pagePath);
547
529
  if (cached) {
548
530
  return cached;
@@ -558,14 +540,14 @@ var routePropsCache, cacheRouteData = (pagePath, data) => {
558
540
  return html.replace("</html>", `${snippet}</html>`);
559
541
  }
560
542
  return html + snippet;
561
- }, injectSsrScripts = (html, requestId, indexPath, props) => {
543
+ }, injectSsrScripts = (html, requestId, indexPath, requestContext) => {
562
544
  let result = html;
563
545
  const registeredScripts = getAndClearClientScripts(requestId);
564
546
  if (registeredScripts.length > 0) {
565
547
  result = injectBeforeClose(result, generateClientScriptCode(registeredScripts));
566
548
  }
567
- if (props) {
568
- result = injectBeforeClose(result, `<script>window.__ABS_ANGULAR_PAGE_PROPS__ = ${JSON.stringify(props)};</script>`);
549
+ if (requestContext !== undefined) {
550
+ result = injectBeforeClose(result, `<script>window.__ABS_ANGULAR_REQUEST_CONTEXT__ = ${JSON.stringify(requestContext)};</script>`);
569
551
  }
570
552
  if (indexPath) {
571
553
  const escapedIndexPath = JSON.stringify(indexPath);
@@ -595,7 +577,7 @@ var routePropsCache, cacheRouteData = (pagePath, data) => {
595
577
  };
596
578
  var init_ssrRender = __esm(() => {
597
579
  init_registerClientScript();
598
- routePropsCache = new Map;
580
+ routeContextCache = new Map;
599
581
  selectorCache = new Map;
600
582
  });
601
583
 
@@ -2978,6 +2960,16 @@ var init_logger = __esm(() => {
2978
2960
  };
2979
2961
  });
2980
2962
 
2963
+ // src/utils/generatedDir.ts
2964
+ var exports_generatedDir = {};
2965
+ __export(exports_generatedDir, {
2966
+ getGeneratedRoot: () => getGeneratedRoot,
2967
+ getFrameworkGeneratedDir: () => getFrameworkGeneratedDir
2968
+ });
2969
+ import { join as join6 } from "path";
2970
+ var GENERATED_DIR_NAME = "generated", ABSOLUTE_CACHE_DIR_NAME = ".absolutejs", getGeneratedRoot = (projectRoot = process.cwd()) => join6(projectRoot, ABSOLUTE_CACHE_DIR_NAME, GENERATED_DIR_NAME), getFrameworkGeneratedDir = (framework, projectRoot = process.cwd()) => join6(getGeneratedRoot(projectRoot), framework);
2971
+ var init_generatedDir = () => {};
2972
+
2981
2973
  // src/islands/sourceMetadata.ts
2982
2974
  var islandFrameworks2, islandHydrationModes2, isIslandFramework2 = (value) => islandFrameworks2.some((framework) => framework === value), isIslandHydrate2 = (value) => islandHydrationModes2.some((hydrate) => hydrate === value), parseIslandTagAttributes = (attributeString) => {
2983
2975
  const frameworkMatch = attributeString.match(/\bframework\s*=\s*["']([^"']+)["']/);
@@ -3516,16 +3508,6 @@ var init_lowerDeferSyntax = __esm(() => {
3516
3508
  init_constants();
3517
3509
  });
3518
3510
 
3519
- // src/utils/generatedDir.ts
3520
- var exports_generatedDir = {};
3521
- __export(exports_generatedDir, {
3522
- getGeneratedRoot: () => getGeneratedRoot,
3523
- getFrameworkGeneratedDir: () => getFrameworkGeneratedDir
3524
- });
3525
- import { join as join6 } from "path";
3526
- var GENERATED_DIR_NAME = "generated", ABSOLUTE_CACHE_DIR_NAME = ".absolutejs", getGeneratedRoot = (projectRoot = process.cwd()) => join6(projectRoot, ABSOLUTE_CACHE_DIR_NAME, GENERATED_DIR_NAME), getFrameworkGeneratedDir = (framework, projectRoot = process.cwd()) => join6(getGeneratedRoot(projectRoot), framework);
3527
- var init_generatedDir = () => {};
3528
-
3529
3511
  // src/build/compileAngular.ts
3530
3512
  var exports_compileAngular = {};
3531
3513
  __export(exports_compileAngular, {
@@ -3535,8 +3517,8 @@ __export(exports_compileAngular, {
3535
3517
  compileAngularFile: () => compileAngularFile,
3536
3518
  compileAngular: () => compileAngular
3537
3519
  });
3538
- import { existsSync as existsSync4, readFileSync as readFileSync4, promises as fs } from "fs";
3539
- import { join as join7, basename as basename3, sep, dirname as dirname4, resolve as resolve6, relative as relative4 } from "path";
3520
+ import { existsSync as existsSync5, readFileSync as readFileSync4, promises as fs } from "fs";
3521
+ import { join as join8, basename as basename3, sep, dirname as dirname4, resolve as resolve6, relative as relative4 } from "path";
3540
3522
  var {Glob } = globalThis.Bun;
3541
3523
  import ts from "typescript";
3542
3524
  var traceAngularPhase = async (name, fn, metadata) => {
@@ -3579,12 +3561,12 @@ var traceAngularPhase = async (name, fn, metadata) => {
3579
3561
  `${candidate}.tsx`,
3580
3562
  `${candidate}.js`,
3581
3563
  `${candidate}.jsx`,
3582
- join7(candidate, "index.ts"),
3583
- join7(candidate, "index.tsx"),
3584
- join7(candidate, "index.js"),
3585
- join7(candidate, "index.jsx")
3564
+ join8(candidate, "index.ts"),
3565
+ join8(candidate, "index.tsx"),
3566
+ join8(candidate, "index.js"),
3567
+ join8(candidate, "index.jsx")
3586
3568
  ];
3587
- return candidates.find((file) => existsSync4(file));
3569
+ return candidates.find((file) => existsSync5(file));
3588
3570
  }, createLegacyAngularAnimationUsageResolver = (rootDir) => {
3589
3571
  const baseDir = resolve6(rootDir);
3590
3572
  const tsconfigAliases = readTsconfigPathAliases();
@@ -3618,9 +3600,9 @@ var traceAngularPhase = async (name, fn, metadata) => {
3618
3600
  });
3619
3601
  }
3620
3602
  const resolved = resolve6(actualPath);
3621
- const cached = scanCache.get(resolved);
3622
- if (cached)
3623
- return cached;
3603
+ const cached2 = scanCache.get(resolved);
3604
+ if (cached2)
3605
+ return cached2;
3624
3606
  const promise = (async () => {
3625
3607
  let sourceCode;
3626
3608
  try {
@@ -3665,11 +3647,11 @@ var traceAngularPhase = async (name, fn, metadata) => {
3665
3647
  }, resolveDevClientDir = () => {
3666
3648
  const projectRoot = process.cwd();
3667
3649
  const fromSource = resolve6(import.meta.dir, "../dev/client");
3668
- if (existsSync4(fromSource) && fromSource.startsWith(projectRoot)) {
3650
+ if (existsSync5(fromSource) && fromSource.startsWith(projectRoot)) {
3669
3651
  return fromSource;
3670
3652
  }
3671
3653
  const fromNodeModules = resolve6(projectRoot, "node_modules/@absolutejs/absolute/dist/dev/client");
3672
- if (existsSync4(fromNodeModules))
3654
+ if (existsSync5(fromNodeModules))
3673
3655
  return fromNodeModules;
3674
3656
  return resolve6(import.meta.dir, "./dev/client");
3675
3657
  }, devClientDir, hmrClientPath, formatDiagnosticMessage = (diagnostic) => {
@@ -3715,11 +3697,11 @@ var traceAngularPhase = async (name, fn, metadata) => {
3715
3697
  return `${path}${query}`;
3716
3698
  const importerDir = dirname4(importerOutputPath);
3717
3699
  const fileCandidate = resolve6(importerDir, `${path}.js`);
3718
- if (outputFiles?.has(fileCandidate) || existsSync4(fileCandidate)) {
3700
+ if (outputFiles?.has(fileCandidate) || existsSync5(fileCandidate)) {
3719
3701
  return `${path}.js${query}`;
3720
3702
  }
3721
3703
  const indexCandidate = resolve6(importerDir, path, "index.js");
3722
- if (outputFiles?.has(indexCandidate) || existsSync4(indexCandidate)) {
3704
+ if (outputFiles?.has(indexCandidate) || existsSync5(indexCandidate)) {
3723
3705
  return `${path}/index.js${query}`;
3724
3706
  }
3725
3707
  return `${path}.js${query}`;
@@ -3752,12 +3734,12 @@ var traceAngularPhase = async (name, fn, metadata) => {
3752
3734
  `${basePath}.tsx`,
3753
3735
  `${basePath}.mts`,
3754
3736
  `${basePath}.cts`,
3755
- join7(basePath, "index.ts"),
3756
- join7(basePath, "index.tsx"),
3757
- join7(basePath, "index.mts"),
3758
- join7(basePath, "index.cts")
3737
+ join8(basePath, "index.ts"),
3738
+ join8(basePath, "index.tsx"),
3739
+ join8(basePath, "index.mts"),
3740
+ join8(basePath, "index.cts")
3759
3741
  ];
3760
- return candidates.map((candidate) => resolve6(candidate)).find((candidate) => existsSync4(candidate) && !candidate.endsWith(".d.ts")) ?? null;
3742
+ return candidates.map((candidate) => resolve6(candidate)).find((candidate) => existsSync5(candidate) && !candidate.endsWith(".d.ts")) ?? null;
3761
3743
  }, readFileForAotTransform = async (fileName, readFile2) => {
3762
3744
  const hostSource = readFile2?.(fileName);
3763
3745
  if (typeof hostSource === "string")
@@ -3781,15 +3763,15 @@ var traceAngularPhase = async (name, fn, metadata) => {
3781
3763
  const paths = [];
3782
3764
  const templateUrlMatch = findUncommentedMatch(source, /templateUrl\s*:\s*['"]([^'"]+)['"]/);
3783
3765
  if (templateUrlMatch?.[1])
3784
- paths.push(join7(fileDir, templateUrlMatch[1]));
3766
+ paths.push(join8(fileDir, templateUrlMatch[1]));
3785
3767
  const styleUrlMatch = findUncommentedMatch(source, /styleUrl\s*:\s*['"]([^'"]+)['"]/);
3786
3768
  if (styleUrlMatch?.[1])
3787
- paths.push(join7(fileDir, styleUrlMatch[1]));
3769
+ paths.push(join8(fileDir, styleUrlMatch[1]));
3788
3770
  const styleUrlsMatch = findUncommentedMatch(source, /styleUrls\s*:\s*\[([^\]]+)\]/);
3789
3771
  const urlMatches = styleUrlsMatch?.[1]?.match(/['"]([^'"]+)['"]/g);
3790
3772
  if (urlMatches) {
3791
3773
  for (const urlMatch of urlMatches) {
3792
- paths.push(join7(fileDir, urlMatch.replace(/['"]/g, "")));
3774
+ paths.push(join8(fileDir, urlMatch.replace(/['"]/g, "")));
3793
3775
  }
3794
3776
  }
3795
3777
  return paths.map((path) => resolve6(path));
@@ -3823,7 +3805,7 @@ var traceAngularPhase = async (name, fn, metadata) => {
3823
3805
  safeStableStringify(stylePreprocessors ?? null)
3824
3806
  ].join("\x00");
3825
3807
  const cacheKey = Bun.hash(cacheInput).toString(BASE_36_RADIX);
3826
- return join7(process.cwd(), ".absolutejs", "cache", "angular-resources", `${cacheKey}.json`);
3808
+ return join8(process.cwd(), ".absolutejs", "cache", "angular-resources", `${cacheKey}.json`);
3827
3809
  }, precomputeAotResourceTransforms = async (inputPaths, readFile2, stylePreprocessors) => {
3828
3810
  const transformedSources = new Map;
3829
3811
  const visited = new Set;
@@ -3838,16 +3820,16 @@ var traceAngularPhase = async (name, fn, metadata) => {
3838
3820
  if (visited.has(resolvedPath))
3839
3821
  return;
3840
3822
  visited.add(resolvedPath);
3841
- if (!existsSync4(resolvedPath) || resolvedPath.endsWith(".d.ts"))
3823
+ if (!existsSync5(resolvedPath) || resolvedPath.endsWith(".d.ts"))
3842
3824
  return;
3843
3825
  stats.filesVisited += 1;
3844
3826
  const source = await readFileForAotTransform(resolvedPath, readFile2);
3845
3827
  const cachePath = await resolveResourceTransformCachePath(resolvedPath, source, stylePreprocessors);
3846
- const cached = await readResourceCacheFile(cachePath);
3828
+ const cached2 = await readResourceCacheFile(cachePath);
3847
3829
  let transformedSource;
3848
- if (cached) {
3830
+ if (cached2) {
3849
3831
  stats.cacheHits += 1;
3850
- transformedSource = cached.source;
3832
+ transformedSource = cached2.source;
3851
3833
  } else {
3852
3834
  stats.cacheMisses += 1;
3853
3835
  const transformed = await inlineResources(source, dirname4(resolvedPath), stylePreprocessors);
@@ -3869,7 +3851,7 @@ var traceAngularPhase = async (name, fn, metadata) => {
3869
3851
  return { stats, transformedSources };
3870
3852
  }, compileAngularFiles = async (inputPaths, outDir, stylePreprocessors) => {
3871
3853
  const islandMetadataByOutputPath = await traceAngularPhase("aot/island-metadata", () => new Map(inputPaths.map((inputPath) => {
3872
- const outputPath = resolve6(join7(outDir, relative4(process.cwd(), resolve6(inputPath)).replace(/\.[cm]?[tj]sx?$/, ".js")));
3854
+ const outputPath = resolve6(join8(outDir, relative4(process.cwd(), resolve6(inputPath)).replace(/\.[cm]?[tj]sx?$/, ".js")));
3873
3855
  return [
3874
3856
  outputPath,
3875
3857
  buildIslandMetadataExports(readFileSync4(inputPath, "utf-8"))
@@ -3916,7 +3898,7 @@ var traceAngularPhase = async (name, fn, metadata) => {
3916
3898
  const originalGetSourceFile = host.getSourceFile;
3917
3899
  host.getSourceFile = (fileName, languageVersion, onError) => {
3918
3900
  if (fileName.startsWith("lib.") && fileName.endsWith(".d.ts") && tsLibDir) {
3919
- const resolvedPath = join7(tsLibDir, fileName);
3901
+ const resolvedPath = join8(tsLibDir, fileName);
3920
3902
  return originalGetSourceFile?.call(host, resolvedPath, languageVersion, onError);
3921
3903
  }
3922
3904
  return originalGetSourceFile?.call(host, fileName, languageVersion, onError);
@@ -3971,7 +3953,7 @@ var traceAngularPhase = async (name, fn, metadata) => {
3971
3953
  const entries = await traceAngularPhase("aot/postprocess-emitted-js", () => {
3972
3954
  const rawEntries = Object.entries(emitted).filter(([fileName]) => fileName.endsWith(".js")).map(([fileName, content]) => ({
3973
3955
  content,
3974
- target: join7(outDir, fileName)
3956
+ target: join8(outDir, fileName)
3975
3957
  }));
3976
3958
  const outputFiles = new Set(rawEntries.map(({ target }) => resolve6(target)));
3977
3959
  return rawEntries.map(({ content, target }) => {
@@ -4012,7 +3994,7 @@ var traceAngularPhase = async (name, fn, metadata) => {
4012
3994
  return null;
4013
3995
  }, resolveAngularDeferImportSpecifier = () => {
4014
3996
  const sourceEntry = resolve6(import.meta.dir, "../angular/components/index.ts");
4015
- if (existsSync4(sourceEntry)) {
3997
+ if (existsSync5(sourceEntry)) {
4016
3998
  return sourceEntry.replace(/\\/g, "/");
4017
3999
  }
4018
4000
  return "@absolutejs/absolute/angular/components";
@@ -4140,7 +4122,7 @@ ${slot.resolvedBindings.map((binding) => ` "${binding.key}": this.__absoluteDef
4140
4122
  ${fields}
4141
4123
  `);
4142
4124
  }, readAndEscapeFile = async (filePath, stylePreprocessors) => {
4143
- if (!existsSync4(filePath)) {
4125
+ if (!existsSync5(filePath)) {
4144
4126
  throw new Error(`Unable to inline Angular style resource: file not found at ${filePath}`);
4145
4127
  }
4146
4128
  const content = await compileStyleFileIfNeeded(filePath, stylePreprocessors);
@@ -4148,8 +4130,8 @@ ${fields}
4148
4130
  }, inlineTemplateAndLowerDefer = async (source, fileDir) => {
4149
4131
  const templateUrlMatch = findUncommentedMatch(source, /templateUrl\s*:\s*['"]([^'"]+)['"]/);
4150
4132
  if (templateUrlMatch?.[1]) {
4151
- const templatePath = join7(fileDir, templateUrlMatch[1]);
4152
- if (!existsSync4(templatePath)) {
4133
+ const templatePath = join8(fileDir, templateUrlMatch[1]);
4134
+ if (!existsSync5(templatePath)) {
4153
4135
  throw new Error(`Unable to inline Angular templateUrl "${templateUrlMatch[1]}": file not found at ${templatePath}`);
4154
4136
  }
4155
4137
  const templateRaw2 = await fs.readFile(templatePath, "utf-8");
@@ -4179,8 +4161,8 @@ ${fields}
4179
4161
  }, inlineTemplateAndLowerDeferSync = (source, fileDir) => {
4180
4162
  const templateUrlMatch = findUncommentedMatch(source, /templateUrl\s*:\s*['"]([^'"]+)['"]/);
4181
4163
  if (templateUrlMatch?.[1]) {
4182
- const templatePath = join7(fileDir, templateUrlMatch[1]);
4183
- if (!existsSync4(templatePath)) {
4164
+ const templatePath = join8(fileDir, templateUrlMatch[1]);
4165
+ if (!existsSync5(templatePath)) {
4184
4166
  throw new Error(`Unable to inline Angular templateUrl "${templateUrlMatch[1]}": file not found at ${templatePath}`);
4185
4167
  }
4186
4168
  const templateRaw2 = readFileSync4(templatePath, "utf-8");
@@ -4216,7 +4198,7 @@ ${fields}
4216
4198
  return source;
4217
4199
  const stylePromises = urlMatches.map((urlMatch) => {
4218
4200
  const styleUrl = urlMatch.replace(/['"]/g, "");
4219
- return readAndEscapeFile(join7(fileDir, styleUrl), stylePreprocessors);
4201
+ return readAndEscapeFile(join8(fileDir, styleUrl), stylePreprocessors);
4220
4202
  });
4221
4203
  const results = await Promise.all(stylePromises);
4222
4204
  const inlinedStyles = results.filter(Boolean).map((escaped) => `\`${escaped}\``);
@@ -4227,7 +4209,7 @@ ${fields}
4227
4209
  const styleUrlMatch = findUncommentedMatch(source, /styleUrl\s*:\s*['"]([^'"]+)['"]/);
4228
4210
  if (!styleUrlMatch?.[1])
4229
4211
  return source;
4230
- const escaped = await readAndEscapeFile(join7(fileDir, styleUrlMatch[1]), stylePreprocessors);
4212
+ const escaped = await readAndEscapeFile(join8(fileDir, styleUrlMatch[1]), stylePreprocessors);
4231
4213
  if (!escaped)
4232
4214
  return source;
4233
4215
  return source.slice(0, styleUrlMatch.index) + `styles: [\`${escaped}\`]` + source.slice(styleUrlMatch.index + styleUrlMatch[0].length);
@@ -4263,12 +4245,12 @@ ${fields}
4263
4245
  `${candidate}.js`,
4264
4246
  `${candidate}.jsx`,
4265
4247
  `${candidate}.json`,
4266
- join7(candidate, "index.ts"),
4267
- join7(candidate, "index.tsx"),
4268
- join7(candidate, "index.js"),
4269
- join7(candidate, "index.jsx")
4248
+ join8(candidate, "index.ts"),
4249
+ join8(candidate, "index.tsx"),
4250
+ join8(candidate, "index.js"),
4251
+ join8(candidate, "index.jsx")
4270
4252
  ];
4271
- return candidates.find((file) => existsSync4(file));
4253
+ return candidates.find((file) => existsSync5(file));
4272
4254
  };
4273
4255
  const resolveLocalImport = (specifier, fromDir) => {
4274
4256
  if (specifier.startsWith(".") || specifier.startsWith("/")) {
@@ -4293,7 +4275,7 @@ ${fields}
4293
4275
  const inputDir = dirname4(sourcePath);
4294
4276
  const relativeDir = inputDir.startsWith(baseDir) ? inputDir.substring(baseDir.length + 1) : inputDir;
4295
4277
  const fileBase = basename3(sourcePath).replace(/\.[cm]?[tj]sx?$/, ".js");
4296
- return join7(outDir, relativeDir, fileBase);
4278
+ return join8(outDir, relativeDir, fileBase);
4297
4279
  };
4298
4280
  const withCacheBuster = (specifier) => {
4299
4281
  if (!cacheBuster)
@@ -4340,11 +4322,11 @@ ${fields}
4340
4322
  if (visited.has(resolved))
4341
4323
  return;
4342
4324
  visited.add(resolved);
4343
- if (resolved.endsWith(".json") && existsSync4(resolved)) {
4325
+ if (resolved.endsWith(".json") && existsSync5(resolved)) {
4344
4326
  const inputDir2 = dirname4(resolved);
4345
4327
  const relativeDir2 = inputDir2.startsWith(baseDir) ? inputDir2.substring(baseDir.length + 1) : inputDir2;
4346
- const targetDir2 = join7(outDir, relativeDir2);
4347
- const targetPath2 = join7(targetDir2, basename3(resolved));
4328
+ const targetDir2 = join8(outDir, relativeDir2);
4329
+ const targetPath2 = join8(targetDir2, basename3(resolved));
4348
4330
  await fs.mkdir(targetDir2, { recursive: true });
4349
4331
  await fs.copyFile(resolved, targetPath2);
4350
4332
  allOutputs.push(targetPath2);
@@ -4353,7 +4335,7 @@ ${fields}
4353
4335
  let actualPath = resolved;
4354
4336
  if (!actualPath.endsWith(".ts"))
4355
4337
  actualPath += ".ts";
4356
- if (!existsSync4(actualPath))
4338
+ if (!existsSync5(actualPath))
4357
4339
  return;
4358
4340
  let sourceCode = await fs.readFile(actualPath, "utf-8");
4359
4341
  const inlined = await inlineResources(sourceCode, dirname4(actualPath), stylePreprocessors);
@@ -4361,7 +4343,7 @@ ${fields}
4361
4343
  const inputDir = dirname4(actualPath);
4362
4344
  const relativeDir = inputDir.startsWith(baseDir) ? inputDir.substring(baseDir.length + 1) : inputDir;
4363
4345
  const fileBase = basename3(actualPath).replace(/\.[cm]?[tj]sx?$/, ".js");
4364
- const targetDir = join7(outDir, relativeDir);
4346
+ const targetDir = join8(outDir, relativeDir);
4365
4347
  const targetPath = toOutputPath(actualPath);
4366
4348
  const localImports = [];
4367
4349
  const importRewrites = new Map;
@@ -4391,7 +4373,7 @@ ${fields}
4391
4373
  const isEntry = resolve6(actualPath) === resolve6(entryPath);
4392
4374
  const contentHash = Bun.hash(sourceCode).toString(BASE_36_RADIX);
4393
4375
  const cacheKey = actualPath;
4394
- const shouldWriteFile = cacheBuster && isEntry ? true : jitContentCache.get(cacheKey) !== contentHash || !existsSync4(targetPath);
4376
+ const shouldWriteFile = cacheBuster && isEntry ? true : jitContentCache.get(cacheKey) !== contentHash || !existsSync5(targetPath);
4395
4377
  if (shouldWriteFile) {
4396
4378
  const processedContent = transpileAndRewrite(sourceCode, relativeDir, actualPath, importRewrites);
4397
4379
  await fs.mkdir(targetDir, { recursive: true });
@@ -4403,7 +4385,7 @@ ${fields}
4403
4385
  };
4404
4386
  await transpileFile(inputPath);
4405
4387
  const entryOutputPath = toOutputPath(entryPath);
4406
- if (existsSync4(entryOutputPath)) {
4388
+ if (existsSync5(entryOutputPath)) {
4407
4389
  const entryOutput = await fs.readFile(entryOutputPath, "utf-8");
4408
4390
  const withoutLegacyFlag = entryOutput.replace(/\nexport const __ABSOLUTE_PAGE_USES_LEGACY_ANIMATIONS__ = true;\n?/g, `
4409
4391
  `);
@@ -4422,23 +4404,23 @@ export const __ABSOLUTE_PAGE_USES_LEGACY_ANIMATIONS__ = true;
4422
4404
  return { clientPaths: [...emptyPaths], serverPaths: [...emptyPaths] };
4423
4405
  }
4424
4406
  const compiledRoot = compiledParent;
4425
- const indexesDir = join7(compiledParent, "indexes");
4407
+ const indexesDir = join8(compiledParent, "indexes");
4426
4408
  await traceAngularPhase("setup/create-indexes-dir", () => fs.mkdir(indexesDir, { recursive: true }));
4427
4409
  const aotOutputs = hmr ? [] : await traceAngularPhase("aot/compile-files", () => compileAngularFiles(entryPoints.map((entry) => resolve6(entry)), compiledRoot, stylePreprocessors), { entries: entryPoints.length });
4428
4410
  if (!hmr) {
4429
4411
  await traceAngularPhase("aot/copy-json-resources", async () => {
4430
4412
  const cwd = process.cwd();
4431
4413
  const angularSrcDir = resolve6(outRoot);
4432
- if (!existsSync4(angularSrcDir))
4414
+ if (!existsSync5(angularSrcDir))
4433
4415
  return;
4434
4416
  const jsonGlob = new Glob("**/*.json");
4435
4417
  for (const rel of jsonGlob.scanSync({
4436
4418
  absolute: false,
4437
4419
  cwd: angularSrcDir
4438
4420
  })) {
4439
- const sourcePath = join7(angularSrcDir, rel);
4421
+ const sourcePath = join8(angularSrcDir, rel);
4440
4422
  const cwdRel = relative4(cwd, sourcePath);
4441
- const targetPath = join7(compiledRoot, cwdRel);
4423
+ const targetPath = join8(compiledRoot, cwdRel);
4442
4424
  await fs.mkdir(dirname4(targetPath), { recursive: true });
4443
4425
  await fs.copyFile(sourcePath, targetPath);
4444
4426
  }
@@ -4455,24 +4437,24 @@ export const __ABSOLUTE_PAGE_USES_LEGACY_ANIMATIONS__ = true;
4455
4437
  const fileBase = basename3(resolvedEntry).replace(/\.[tj]s$/, "");
4456
4438
  const jsName = `${fileBase}.js`;
4457
4439
  const compiledFallbackPaths = [
4458
- join7(compiledRoot, relativeEntry),
4459
- join7(compiledRoot, "pages", jsName),
4460
- join7(compiledRoot, jsName)
4440
+ join8(compiledRoot, relativeEntry),
4441
+ join8(compiledRoot, "pages", jsName),
4442
+ join8(compiledRoot, jsName)
4461
4443
  ].map((file) => resolve6(file));
4462
4444
  const resolveRawServerFile = (candidatePaths) => {
4463
4445
  const normalizedCandidates = [
4464
4446
  ...candidatePaths.map((file) => resolve6(file)),
4465
4447
  ...compiledFallbackPaths
4466
4448
  ];
4467
- let candidate = normalizedCandidates.find((file) => existsSync4(file) && file.endsWith(`${sep}${relativeEntry}`));
4449
+ let candidate = normalizedCandidates.find((file) => existsSync5(file) && file.endsWith(`${sep}${relativeEntry}`));
4468
4450
  if (!candidate) {
4469
- candidate = normalizedCandidates.find((file) => existsSync4(file) && file.endsWith(`${sep}pages${sep}${jsName}`));
4451
+ candidate = normalizedCandidates.find((file) => existsSync5(file) && file.endsWith(`${sep}pages${sep}${jsName}`));
4470
4452
  }
4471
4453
  if (!candidate) {
4472
- candidate = normalizedCandidates.find((file) => existsSync4(file) && file.endsWith(`${sep}${jsName}`));
4454
+ candidate = normalizedCandidates.find((file) => existsSync5(file) && file.endsWith(`${sep}${jsName}`));
4473
4455
  }
4474
4456
  if (!candidate) {
4475
- candidate = normalizedCandidates.find((file) => existsSync4(file));
4457
+ candidate = normalizedCandidates.find((file) => existsSync5(file));
4476
4458
  }
4477
4459
  return candidate;
4478
4460
  };
@@ -4480,11 +4462,11 @@ export const __ABSOLUTE_PAGE_USES_LEGACY_ANIMATIONS__ = true;
4480
4462
  if (!rawServerFile) {
4481
4463
  rawServerFile = await traceAngularPhase("wrapper/resolve-server-output-fallback", () => resolveRawServerFile([]), { entry: resolvedEntry });
4482
4464
  }
4483
- if (rawServerFile && !existsSync4(rawServerFile)) {
4465
+ if (rawServerFile && !existsSync5(rawServerFile)) {
4484
4466
  outputs = hmr ? await compileEntry() : aotOutputs;
4485
4467
  rawServerFile = await traceAngularPhase("wrapper/resolve-server-output-retry", () => resolveRawServerFile(outputs), { entry: resolvedEntry });
4486
4468
  }
4487
- if (!rawServerFile || !existsSync4(rawServerFile)) {
4469
+ if (!rawServerFile || !existsSync5(rawServerFile)) {
4488
4470
  throw new Error(`Compiled output not found for ${entry}. Looking for: ${jsName}. Available: ${[
4489
4471
  ...outputs,
4490
4472
  ...compiledFallbackPaths
@@ -4505,8 +4487,8 @@ export const __ABSOLUTE_PAGE_USES_LEGACY_ANIMATIONS__ = true;
4505
4487
  const usesLegacyAnimations = await traceAngularPhase("wrapper/detect-legacy-animations", () => usesLegacyAngularAnimations(resolvedEntry), { entry: resolvedEntry });
4506
4488
  const serverContentHash = Bun.hash(original).toString(BASE_36_RADIX);
4507
4489
  const cachedWrapper = wrapperOutputCache.get(resolvedEntry);
4508
- const clientFile = join7(indexesDir, jsName);
4509
- if (hmr && cachedWrapper && cachedWrapper.serverHash === serverContentHash && existsSync4(clientFile) && (usesLegacyAnimations || !original.includes("__ABSOLUTE_PAGE_USES_LEGACY_ANIMATIONS__")) && (!usesLegacyAnimations || original.includes("__ABSOLUTE_PAGE_USES_LEGACY_ANIMATIONS__"))) {
4490
+ const clientFile = join8(indexesDir, jsName);
4491
+ if (hmr && cachedWrapper && cachedWrapper.serverHash === serverContentHash && existsSync5(clientFile) && (usesLegacyAnimations || !original.includes("__ABSOLUTE_PAGE_USES_LEGACY_ANIMATIONS__")) && (!usesLegacyAnimations || original.includes("__ABSOLUTE_PAGE_USES_LEGACY_ANIMATIONS__"))) {
4510
4492
  return {
4511
4493
  clientPath: clientFile,
4512
4494
  indexUnchanged: true,
@@ -4533,6 +4515,14 @@ export const __ABSOLUTE_PAGE_USES_LEGACY_ANIMATIONS__ = true;
4533
4515
  await traceAngularPhase("wrapper/write-server-output", () => fs.writeFile(rawServerFile, rewritten, "utf-8"), { entry: resolvedEntry });
4534
4516
  const relativePath = relative4(indexesDir, rawServerFile).replace(/\\/g, "/");
4535
4517
  const normalizedImportPath = relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
4518
+ const manifestKeyForProviders = toPascal(fileBase);
4519
+ const providersFilePath = join8(compiledParent, "providers", `${manifestKeyForProviders}.providers.ts`);
4520
+ const hasGeneratedProviders = existsSync5(providersFilePath);
4521
+ const providersImportPath = hasGeneratedProviders ? (() => {
4522
+ const rel = relative4(indexesDir, providersFilePath.replace(/\.ts$/, "")).replace(/\\/g, "/");
4523
+ return rel.startsWith(".") ? rel : `./${rel}`;
4524
+ })() : null;
4525
+ const generatedProvidersImport = providersImportPath ? `import { providers as generatedProviders } from '${providersImportPath}';` : "var generatedProviders = null;";
4536
4526
  const hmrPreamble = hmr ? `window.__HMR_FRAMEWORK__ = "angular";
4537
4527
  import "${hmrClientPath}";
4538
4528
  ` : "";
@@ -4541,32 +4531,31 @@ import '@angular/compiler';
4541
4531
  import { bootstrapApplication } from '@angular/platform-browser';
4542
4532
  import { provideClientHydration } from '@angular/platform-browser';
4543
4533
  import { withHttpTransferCacheOptions } from '@angular/platform-browser';
4544
- import { provideZonelessChangeDetection } from '@angular/core';
4534
+ import { provideZonelessChangeDetection, REQUEST_CONTEXT } from '@angular/core';
4545
4535
  import * as pageModule from '${normalizedImportPath}';
4536
+ ${generatedProvidersImport}
4546
4537
 
4547
4538
  var ${componentClassName} = pageModule.default;
4548
- var toScreamingSnake = function(str) {
4549
- return str.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase();
4550
- };
4551
- var isInjectionToken = function(value) {
4552
- return Boolean(value) && typeof value === 'object' && value.ngMetadataName === 'InjectionToken';
4553
- };
4554
- var pageProps = window.__ABS_ANGULAR_PAGE_PROPS__ || {};
4539
+ // REQUEST_CONTEXT is hydrated from the SSR-serialized payload so client-side
4540
+ // \`inject(REQUEST_CONTEXT)\` (or \`usePageContext<T>()\`) returns the same
4541
+ // object the server rendered with \u2014 no second round-trip, no transferState
4542
+ // dance for callers.
4543
+ var requestContext = Object.prototype.hasOwnProperty.call(window, '__ABS_ANGULAR_REQUEST_CONTEXT__')
4544
+ ? window.__ABS_ANGULAR_REQUEST_CONTEXT__
4545
+ : null;
4555
4546
  var pageHasIslands = Boolean(pageModule.__ABSOLUTE_PAGE_HAS_ISLANDS__) || Boolean(document.querySelector('[data-island="true"]'));
4556
4547
  var pageHasRawStreamingSlots = Boolean(document.querySelector('[data-absolute-raw-slot="true"]'));
4557
4548
  var pageHasStreamingSlots = Boolean(document.querySelector('[data-absolute-slot="true"]'));
4558
- var propProviders = Object.entries(pageProps).map(function(entry) {
4559
- var propName = entry[0];
4560
- var propValue = entry[1];
4561
- var token = pageModule[toScreamingSnake(propName)];
4562
- return isInjectionToken(token) ? { provide: token, useValue: propValue } : null;
4563
- }).filter(Boolean);
4564
- // Page-level providers, opt-in via \`export const providers = [...]\` in the
4565
- // page module. Required so DI tokens that the component (or any service it
4566
- // injects) needs are available client-side too \u2014 without these, services
4567
- // that worked in SSR fail with NG0201 after hydration.
4568
- var maybePageProviders = Reflect.get(pageModule, 'providers');
4569
- var pageProviders = Array.isArray(maybePageProviders) ? maybePageProviders : [];
4549
+ var contextProviders = [{ provide: REQUEST_CONTEXT, useValue: requestContext }];
4550
+ // Page-level providers come from the build-generated providers file
4551
+ // (emitted by \`runAngularHandlerScan\` based on the page's
4552
+ // \`handleAngularPageRequest({...})\` call). Falls back to the legacy
4553
+ // \`export const providers\` on the page module for projects that
4554
+ // haven't migrated yet.
4555
+ var legacyPageProviders = Reflect.get(pageModule, 'providers');
4556
+ var pageProviders = Array.isArray(generatedProviders)
4557
+ ? generatedProviders
4558
+ : (Array.isArray(legacyPageProviders) ? legacyPageProviders : []);
4570
4559
  var absoluteHttpTransferCacheOptions = {
4571
4560
  includePostRequests: false,
4572
4561
  includeRequestsWithAuthHeaders: false,
@@ -4613,7 +4602,7 @@ if (!window.__HMR_SKIP_HYDRATION__ && !pageHasIslands) {
4613
4602
  }
4614
4603
  delete window.__HMR_SKIP_HYDRATION__;
4615
4604
  providers.push.apply(providers, pageProviders);
4616
- providers.push.apply(providers, propProviders);
4605
+ providers.push.apply(providers, contextProviders);
4617
4606
  window.__ABS_SLOT_HYDRATION_PENDING__ = pageHasRawStreamingSlots;
4618
4607
 
4619
4608
  if (pageHasRawStreamingSlots) {
@@ -4641,32 +4630,31 @@ import '@angular/compiler';
4641
4630
  import { bootstrapApplication } from '@angular/platform-browser';
4642
4631
  import { provideClientHydration } from '@angular/platform-browser';
4643
4632
  import { withHttpTransferCacheOptions } from '@angular/platform-browser';
4644
- import { enableProdMode, provideZonelessChangeDetection } from '@angular/core';
4633
+ import { enableProdMode, provideZonelessChangeDetection, REQUEST_CONTEXT } from '@angular/core';
4645
4634
  import * as pageModule from '${normalizedImportPath}';
4635
+ ${generatedProvidersImport}
4646
4636
 
4647
4637
  var ${componentClassName} = pageModule.default;
4648
- var toScreamingSnake = function(str) {
4649
- return str.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase();
4650
- };
4651
- var isInjectionToken = function(value) {
4652
- return Boolean(value) && typeof value === 'object' && value.ngMetadataName === 'InjectionToken';
4653
- };
4654
- var pageProps = window.__ABS_ANGULAR_PAGE_PROPS__ || {};
4638
+ // REQUEST_CONTEXT is hydrated from the SSR-serialized payload so client-side
4639
+ // \`inject(REQUEST_CONTEXT)\` (or \`usePageContext<T>()\`) returns the same
4640
+ // object the server rendered with \u2014 no second round-trip, no transferState
4641
+ // dance for callers.
4642
+ var requestContext = Object.prototype.hasOwnProperty.call(window, '__ABS_ANGULAR_REQUEST_CONTEXT__')
4643
+ ? window.__ABS_ANGULAR_REQUEST_CONTEXT__
4644
+ : null;
4655
4645
  var pageHasIslands = Boolean(pageModule.__ABSOLUTE_PAGE_HAS_ISLANDS__) || Boolean(document.querySelector('[data-island="true"]'));
4656
4646
  var pageHasRawStreamingSlots = Boolean(document.querySelector('[data-absolute-raw-slot="true"]'));
4657
4647
  var pageHasStreamingSlots = Boolean(document.querySelector('[data-absolute-slot="true"]'));
4658
- var propProviders = Object.entries(pageProps).map(function(entry) {
4659
- var propName = entry[0];
4660
- var propValue = entry[1];
4661
- var token = pageModule[toScreamingSnake(propName)];
4662
- return isInjectionToken(token) ? { provide: token, useValue: propValue } : null;
4663
- }).filter(Boolean);
4664
- // Page-level providers, opt-in via \`export const providers = [...]\` in the
4665
- // page module. Required so DI tokens that the component (or any service it
4666
- // injects) needs are available client-side too \u2014 without these, services
4667
- // that worked in SSR fail with NG0201 after hydration.
4668
- var maybePageProviders = Reflect.get(pageModule, 'providers');
4669
- var pageProviders = Array.isArray(maybePageProviders) ? maybePageProviders : [];
4648
+ var contextProviders = [{ provide: REQUEST_CONTEXT, useValue: requestContext }];
4649
+ // Page-level providers come from the build-generated providers file
4650
+ // (emitted by \`runAngularHandlerScan\` based on the page's
4651
+ // \`handleAngularPageRequest({...})\` call). Falls back to the legacy
4652
+ // \`export const providers\` on the page module for projects that
4653
+ // haven't migrated yet.
4654
+ var legacyPageProviders = Reflect.get(pageModule, 'providers');
4655
+ var pageProviders = Array.isArray(generatedProviders)
4656
+ ? generatedProviders
4657
+ : (Array.isArray(legacyPageProviders) ? legacyPageProviders : []);
4670
4658
  var absoluteHttpTransferCacheOptions = {
4671
4659
  includePostRequests: false,
4672
4660
  includeRequestsWithAuthHeaders: false,
@@ -4677,7 +4665,7 @@ var absoluteHttpTransferCacheOptions = {
4677
4665
 
4678
4666
  enableProdMode();
4679
4667
 
4680
- var providers = [provideZonelessChangeDetection()].concat(pageProviders).concat(propProviders);
4668
+ var providers = [provideZonelessChangeDetection()].concat(pageProviders).concat(contextProviders);
4681
4669
  if (!pageHasIslands) {
4682
4670
  providers.unshift(provideClientHydration(withHttpTransferCacheOptions(absoluteHttpTransferCacheOptions)));
4683
4671
  }
@@ -4735,7 +4723,7 @@ var init_compileAngular = __esm(() => {
4735
4723
  init_stylePreprocessor();
4736
4724
  init_generatedDir();
4737
4725
  devClientDir = resolveDevClientDir();
4738
- hmrClientPath = join7(devClientDir, "hmrClient.ts").replace(/\\/g, "/");
4726
+ hmrClientPath = join8(devClientDir, "hmrClient.ts").replace(/\\/g, "/");
4739
4727
  jitContentCache = new Map;
4740
4728
  wrapperOutputCache = new Map;
4741
4729
  });
@@ -4905,7 +4893,7 @@ init_constants();
4905
4893
  import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
4906
4894
  import { mkdir as mkdir3, symlink } from "fs/promises";
4907
4895
  import { tmpdir } from "os";
4908
- import { basename as basename4, dirname as dirname5, join as join8, resolve as resolve7 } from "path";
4896
+ import { basename as basename4, dirname as dirname5, join as join9, resolve as resolve7 } from "path";
4909
4897
  import { pathToFileURL as pathToFileURL2 } from "url";
4910
4898
 
4911
4899
  // src/core/islandPageContext.ts
@@ -5742,6 +5730,38 @@ var runWithStreamingSlotWarningScope = (task, metadata) => ensureWarningStorage(
5742
5730
 
5743
5731
  // src/angular/pageHandler.ts
5744
5732
  init_ssrRender();
5733
+
5734
+ // src/angular/loadRouteMounts.ts
5735
+ init_generatedDir();
5736
+ import { existsSync as existsSync4 } from "fs";
5737
+ import { join as join7 } from "path";
5738
+ var cached = null;
5739
+ var loadAngularRouteMounts = async () => {
5740
+ if (cached)
5741
+ return cached;
5742
+ const filePath = join7(getFrameworkGeneratedDir("angular", process.cwd()), "route-mounts.ts");
5743
+ if (!existsSync4(filePath)) {
5744
+ cached = [];
5745
+ return cached;
5746
+ }
5747
+ try {
5748
+ const mod = await import(filePath);
5749
+ cached = mod.routeMounts ?? [];
5750
+ } catch (error) {
5751
+ console.warn("[absolute/angular] failed to load route-mounts:", error);
5752
+ cached = [];
5753
+ }
5754
+ return cached;
5755
+ };
5756
+ var matchAngularBasePath = (mounts, urlPath) => {
5757
+ for (const mount of mounts) {
5758
+ if (mount.pattern.test(urlPath))
5759
+ return mount.basePath;
5760
+ }
5761
+ return "/";
5762
+ };
5763
+
5764
+ // src/angular/pageHandler.ts
5745
5765
  var lastSelector = "angular-page";
5746
5766
  var isRecord5 = (value) => typeof value === "object" && value !== null;
5747
5767
  var isAngularComponent2 = (value) => typeof value === "function";
@@ -5762,11 +5782,11 @@ var ensureAngularCompiler = () => {
5762
5782
  return compilerImportPromise;
5763
5783
  };
5764
5784
  var readAngularPageModule = (value) => isRecord5(value) ? value : null;
5765
- var resolveAngularSsrOutDir = () => process.env.ABSOLUTE_ANGULAR_SSR_OUTDIR ?? join8(tmpdir(), "absolutejs", "generated", "angular-ssr");
5785
+ var resolveAngularSsrOutDir = () => process.env.ABSOLUTE_ANGULAR_SSR_OUTDIR ?? join9(tmpdir(), "absolutejs", "generated", "angular-ssr");
5766
5786
  var createAngularRuntimeCacheBuster = () => `${Date.now().toString(BASE_36_RADIX)}.${Math.random().toString(BASE_36_RADIX).substring(2, RANDOM_ID_END_INDEX)}`;
5767
5787
  var ensureAngularSsrNodeModules = async (outDir) => {
5768
5788
  const outRoot = resolve7(dirname5(dirname5(outDir)));
5769
- const nodeModulesLink = join8(outRoot, "node_modules");
5789
+ const nodeModulesLink = join9(outRoot, "node_modules");
5770
5790
  if (process.env.ABSOLUTE_ANGULAR_SSR_OUTDIR) {
5771
5791
  return;
5772
5792
  }
@@ -5841,11 +5861,6 @@ var resolveRequestRenderUrl = (request) => {
5841
5861
  return "/";
5842
5862
  }
5843
5863
  };
5844
- var assertNoHandlerProviders = (input) => {
5845
- if (!("providers" in input))
5846
- return;
5847
- throw new Error("Angular handler providers are not supported. Export `providers` from the Angular page module, or inject REQUEST / REQUEST_CONTEXT for request-scoped data.");
5848
- };
5849
5864
  var angularSsrContext = new AsyncLocalStorage3;
5850
5865
  setSsrContextGetter(() => angularSsrContext.getStore());
5851
5866
  var handleAngularPageRequest = async (input) => {
@@ -5856,15 +5871,14 @@ var handleAngularPageRequest = async (input) => {
5856
5871
  const resolvedIndexPath = input.indexPath;
5857
5872
  const options = input;
5858
5873
  const resolvedPagePath = input.pagePath;
5859
- const maybeProps = input.props;
5874
+ const maybeRequestContext = input.requestContext;
5860
5875
  const responseInit = input.responseInit ?? {};
5861
5876
  const resolvedUrl = resolveRequestRenderUrl(input.request);
5862
5877
  cacheRouteData(resolvedPagePath, {
5863
5878
  headTag: resolvedHeadTag,
5864
- props: maybeProps
5879
+ requestContext: maybeRequestContext
5865
5880
  });
5866
5881
  try {
5867
- assertNoHandlerProviders(input);
5868
5882
  const handlerCallsite = options?.collectStreamingSlots === true ? undefined : getCurrentRouteRegistrationCallsite() ?? captureStreamingSlotWarningCallsite();
5869
5883
  const renderPageResponse = async () => {
5870
5884
  const baseDeps = await getAngularDeps();
@@ -5881,24 +5895,35 @@ var handleAngularPageRequest = async (input) => {
5881
5895
  const hasIslands = typeof pageModule.__ABSOLUTE_PAGE_HAS_ISLANDS__ === "boolean" ? pageModule.__ABSOLUTE_PAGE_HAS_ISLANDS__ : false;
5882
5896
  const usesLegacyAnimations = pageModule.__ABSOLUTE_PAGE_USES_LEGACY_ANIMATIONS__ === true;
5883
5897
  const deps = baseDeps;
5884
- const tokenMap = discoverTokens(pageModule);
5885
5898
  const selector = resolveSelector(deps, resolvedPagePath, PageComponent);
5886
5899
  lastSelector = selector;
5887
5900
  const htmlString = `<!DOCTYPE html><html>${resolvedHeadTag}<body><${selector}></${selector}></body></html>`;
5888
5901
  resetSsrSanitizer();
5889
5902
  const sanitizer = getSsrSanitizer(deps);
5890
- const pageProvidersExport = Reflect.get(pageModule, "providers");
5891
- const pageProviders = Array.isArray(pageProvidersExport) ? pageProvidersExport : [];
5903
+ const handlerProviders = Array.isArray(input.providers) ? input.providers : [];
5904
+ const legacyProvidersExport = Reflect.get(pageModule, "providers");
5905
+ const legacyPageProviders = handlerProviders.length > 0 ? [] : Array.isArray(legacyProvidersExport) ? legacyProvidersExport : [];
5906
+ const routeMounts = await loadAngularRouteMounts();
5907
+ const requestUrlPath = input.request ? new URL(input.request.url).pathname : "/";
5908
+ const inferredBasePath = matchAngularBasePath(routeMounts, requestUrlPath);
5909
+ const inferredBasePathProvider = inferredBasePath === "/" ? [] : [
5910
+ {
5911
+ provide: deps.APP_BASE_HREF,
5912
+ useValue: inferredBasePath
5913
+ }
5914
+ ];
5892
5915
  const combinedProviders = [
5893
5916
  ...await buildRouterRedirectProviders(deps, responseInit),
5894
- ...pageProviders,
5917
+ ...inferredBasePathProvider,
5918
+ ...handlerProviders,
5919
+ ...legacyPageProviders,
5895
5920
  ...await buildServerAnimationProviders(usesLegacyAnimations)
5896
5921
  ];
5897
- const providers = buildProviders(deps, sanitizer, maybeProps, tokenMap, input.request, input.requestContext, responseInit, combinedProviders);
5922
+ const providers = buildProviders(deps, sanitizer, input.request, maybeRequestContext, responseInit, combinedProviders);
5898
5923
  const rawHtml = await renderAngularApp(deps, PageComponent, providers, htmlString, resolvedUrl);
5899
5924
  const shouldProcessIslands = hasIslands || rawHtml.includes("<absolute-island");
5900
5925
  const htmlWithLoweredIslands = shouldProcessIslands ? await lowerAngularServerIslands(rawHtml) : rawHtml;
5901
- const html = injectIslandPageContext(injectSsrScripts(htmlWithLoweredIslands, requestId, resolvedIndexPath, maybeProps), { hasIslands: shouldProcessIslands });
5926
+ const html = injectIslandPageContext(injectSsrScripts(htmlWithLoweredIslands, requestId, resolvedIndexPath, maybeRequestContext), { hasIslands: shouldProcessIslands });
5902
5927
  return new Response(html, withHtmlContentType(responseInit));
5903
5928
  };
5904
5929
  return await runWithStreamingSlotWarningScope(() => options?.collectStreamingSlots === true ? withRegisteredStreamingSlots(renderPageResponse, options) : renderPageResponse(), { handlerCallsite });
@@ -5937,5 +5962,5 @@ export {
5937
5962
  ABSOLUTE_HTTP_TRANSFER_CACHE_SKIP_HEADER
5938
5963
  };
5939
5964
 
5940
- //# debugId=D08B094C6000F76364756E2164756E21
5965
+ //# debugId=B1E43B86788CDDEA64756E2164756E21
5941
5966
  //# sourceMappingURL=server.js.map