@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
  });
@@ -13846,7 +13834,7 @@ init_constants();
13846
13834
  import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
13847
13835
  import { mkdir as mkdir3, symlink } from "fs/promises";
13848
13836
  import { tmpdir } from "os";
13849
- import { basename as basename4, dirname as dirname5, join as join8, resolve as resolve7 } from "path";
13837
+ import { basename as basename4, dirname as dirname5, join as join9, resolve as resolve7 } from "path";
13850
13838
  import { pathToFileURL as pathToFileURL2 } from "url";
13851
13839
 
13852
13840
  // src/core/islandPageContext.ts
@@ -14683,6 +14671,38 @@ var runWithStreamingSlotWarningScope = (task, metadata) => ensureWarningStorage(
14683
14671
 
14684
14672
  // src/angular/pageHandler.ts
14685
14673
  init_ssrRender();
14674
+
14675
+ // src/angular/loadRouteMounts.ts
14676
+ init_generatedDir();
14677
+ import { existsSync as existsSync4 } from "fs";
14678
+ import { join as join7 } from "path";
14679
+ var cached = null;
14680
+ var loadAngularRouteMounts = async () => {
14681
+ if (cached)
14682
+ return cached;
14683
+ const filePath = join7(getFrameworkGeneratedDir("angular", process.cwd()), "route-mounts.ts");
14684
+ if (!existsSync4(filePath)) {
14685
+ cached = [];
14686
+ return cached;
14687
+ }
14688
+ try {
14689
+ const mod = await import(filePath);
14690
+ cached = mod.routeMounts ?? [];
14691
+ } catch (error) {
14692
+ console.warn("[absolute/angular] failed to load route-mounts:", error);
14693
+ cached = [];
14694
+ }
14695
+ return cached;
14696
+ };
14697
+ var matchAngularBasePath = (mounts, urlPath) => {
14698
+ for (const mount of mounts) {
14699
+ if (mount.pattern.test(urlPath))
14700
+ return mount.basePath;
14701
+ }
14702
+ return "/";
14703
+ };
14704
+
14705
+ // src/angular/pageHandler.ts
14686
14706
  var lastSelector = "angular-page";
14687
14707
  var isRecord5 = (value) => typeof value === "object" && value !== null;
14688
14708
  var isAngularComponent2 = (value) => typeof value === "function";
@@ -14703,11 +14723,11 @@ var ensureAngularCompiler = () => {
14703
14723
  return compilerImportPromise;
14704
14724
  };
14705
14725
  var readAngularPageModule = (value) => isRecord5(value) ? value : null;
14706
- var resolveAngularSsrOutDir = () => process.env.ABSOLUTE_ANGULAR_SSR_OUTDIR ?? join8(tmpdir(), "absolutejs", "generated", "angular-ssr");
14726
+ var resolveAngularSsrOutDir = () => process.env.ABSOLUTE_ANGULAR_SSR_OUTDIR ?? join9(tmpdir(), "absolutejs", "generated", "angular-ssr");
14707
14727
  var createAngularRuntimeCacheBuster = () => `${Date.now().toString(BASE_36_RADIX)}.${Math.random().toString(BASE_36_RADIX).substring(2, RANDOM_ID_END_INDEX)}`;
14708
14728
  var ensureAngularSsrNodeModules = async (outDir) => {
14709
14729
  const outRoot = resolve7(dirname5(dirname5(outDir)));
14710
- const nodeModulesLink = join8(outRoot, "node_modules");
14730
+ const nodeModulesLink = join9(outRoot, "node_modules");
14711
14731
  if (process.env.ABSOLUTE_ANGULAR_SSR_OUTDIR) {
14712
14732
  return;
14713
14733
  }
@@ -14782,11 +14802,6 @@ var resolveRequestRenderUrl = (request) => {
14782
14802
  return "/";
14783
14803
  }
14784
14804
  };
14785
- var assertNoHandlerProviders = (input) => {
14786
- if (!("providers" in input))
14787
- return;
14788
- 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.");
14789
- };
14790
14805
  var angularSsrContext = new AsyncLocalStorage3;
14791
14806
  setSsrContextGetter(() => angularSsrContext.getStore());
14792
14807
  var handleAngularPageRequest = async (input) => {
@@ -14797,15 +14812,14 @@ var handleAngularPageRequest = async (input) => {
14797
14812
  const resolvedIndexPath = input.indexPath;
14798
14813
  const options = input;
14799
14814
  const resolvedPagePath = input.pagePath;
14800
- const maybeProps = input.props;
14815
+ const maybeRequestContext = input.requestContext;
14801
14816
  const responseInit = input.responseInit ?? {};
14802
14817
  const resolvedUrl = resolveRequestRenderUrl(input.request);
14803
14818
  cacheRouteData(resolvedPagePath, {
14804
14819
  headTag: resolvedHeadTag,
14805
- props: maybeProps
14820
+ requestContext: maybeRequestContext
14806
14821
  });
14807
14822
  try {
14808
- assertNoHandlerProviders(input);
14809
14823
  const handlerCallsite = options?.collectStreamingSlots === true ? undefined : getCurrentRouteRegistrationCallsite() ?? captureStreamingSlotWarningCallsite();
14810
14824
  const renderPageResponse = async () => {
14811
14825
  const baseDeps = await getAngularDeps();
@@ -14822,24 +14836,35 @@ var handleAngularPageRequest = async (input) => {
14822
14836
  const hasIslands = typeof pageModule.__ABSOLUTE_PAGE_HAS_ISLANDS__ === "boolean" ? pageModule.__ABSOLUTE_PAGE_HAS_ISLANDS__ : false;
14823
14837
  const usesLegacyAnimations = pageModule.__ABSOLUTE_PAGE_USES_LEGACY_ANIMATIONS__ === true;
14824
14838
  const deps = baseDeps;
14825
- const tokenMap = discoverTokens(pageModule);
14826
14839
  const selector = resolveSelector(deps, resolvedPagePath, PageComponent);
14827
14840
  lastSelector = selector;
14828
14841
  const htmlString = `<!DOCTYPE html><html>${resolvedHeadTag}<body><${selector}></${selector}></body></html>`;
14829
14842
  resetSsrSanitizer();
14830
14843
  const sanitizer = getSsrSanitizer(deps);
14831
- const pageProvidersExport = Reflect.get(pageModule, "providers");
14832
- const pageProviders = Array.isArray(pageProvidersExport) ? pageProvidersExport : [];
14844
+ const handlerProviders = Array.isArray(input.providers) ? input.providers : [];
14845
+ const legacyProvidersExport = Reflect.get(pageModule, "providers");
14846
+ const legacyPageProviders = handlerProviders.length > 0 ? [] : Array.isArray(legacyProvidersExport) ? legacyProvidersExport : [];
14847
+ const routeMounts = await loadAngularRouteMounts();
14848
+ const requestUrlPath = input.request ? new URL(input.request.url).pathname : "/";
14849
+ const inferredBasePath = matchAngularBasePath(routeMounts, requestUrlPath);
14850
+ const inferredBasePathProvider = inferredBasePath === "/" ? [] : [
14851
+ {
14852
+ provide: deps.APP_BASE_HREF,
14853
+ useValue: inferredBasePath
14854
+ }
14855
+ ];
14833
14856
  const combinedProviders = [
14834
14857
  ...await buildRouterRedirectProviders(deps, responseInit),
14835
- ...pageProviders,
14858
+ ...inferredBasePathProvider,
14859
+ ...handlerProviders,
14860
+ ...legacyPageProviders,
14836
14861
  ...await buildServerAnimationProviders(usesLegacyAnimations)
14837
14862
  ];
14838
- const providers = buildProviders(deps, sanitizer, maybeProps, tokenMap, input.request, input.requestContext, responseInit, combinedProviders);
14863
+ const providers = buildProviders(deps, sanitizer, input.request, maybeRequestContext, responseInit, combinedProviders);
14839
14864
  const rawHtml = await renderAngularApp(deps, PageComponent, providers, htmlString, resolvedUrl);
14840
14865
  const shouldProcessIslands = hasIslands || rawHtml.includes("<absolute-island");
14841
14866
  const htmlWithLoweredIslands = shouldProcessIslands ? await lowerAngularServerIslands(rawHtml) : rawHtml;
14842
- const html = injectIslandPageContext(injectSsrScripts(htmlWithLoweredIslands, requestId, resolvedIndexPath, maybeProps), { hasIslands: shouldProcessIslands });
14867
+ const html = injectIslandPageContext(injectSsrScripts(htmlWithLoweredIslands, requestId, resolvedIndexPath, maybeRequestContext), { hasIslands: shouldProcessIslands });
14843
14868
  return new Response(html, withHtmlContentType(responseInit));
14844
14869
  };
14845
14870
  return await runWithStreamingSlotWarningScope(() => options?.collectStreamingSlots === true ? withRegisteredStreamingSlots(renderPageResponse, options) : renderPageResponse(), { handlerCallsite });
@@ -14856,10 +14881,13 @@ var handleAngularPageRequest = async (input) => {
14856
14881
  }
14857
14882
  });
14858
14883
  };
14884
+ // src/angular/composables/usePageContext.ts
14885
+ import { inject, REQUEST_CONTEXT } from "@angular/core";
14886
+ var usePageContext = () => inject(REQUEST_CONTEXT);
14859
14887
  // src/angular/composables/useResource.ts
14860
- import { DestroyRef, inject, signal } from "@angular/core";
14888
+ import { DestroyRef, inject as inject2, signal } from "@angular/core";
14861
14889
  var useResource = (fetcher, options = {}) => {
14862
- const destroyRef = inject(DestroyRef);
14890
+ const destroyRef = inject2(DestroyRef);
14863
14891
  const start = options.start ?? "immediate";
14864
14892
  const data = signal(null);
14865
14893
  const error = signal(null);
@@ -14917,16 +14945,16 @@ var useResource = (fetcher, options = {}) => {
14917
14945
  return { cancel, data, error, loading, mutate, refresh };
14918
14946
  };
14919
14947
  // src/angular/composables/useSubscription.ts
14920
- import { DestroyRef as DestroyRef2, inject as inject2 } from "@angular/core";
14948
+ import { DestroyRef as DestroyRef2, inject as inject3 } from "@angular/core";
14921
14949
  import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
14922
14950
  function useSubscription(observable, observerOrNext) {
14923
- const destroyRef = inject2(DestroyRef2);
14951
+ const destroyRef = inject3(DestroyRef2);
14924
14952
  return observable.pipe(takeUntilDestroyed(destroyRef)).subscribe(typeof observerOrNext === "function" ? { next: observerOrNext } : observerOrNext);
14925
14953
  }
14926
14954
  // src/angular/composables/useTimers.ts
14927
- import { DestroyRef as DestroyRef3, inject as inject3 } from "@angular/core";
14955
+ import { DestroyRef as DestroyRef3, inject as inject4 } from "@angular/core";
14928
14956
  var useTimers = () => {
14929
- const destroyRef = inject3(DestroyRef3);
14957
+ const destroyRef = inject4(DestroyRef3);
14930
14958
  const timeouts = new Set;
14931
14959
  const intervals = new Set;
14932
14960
  const clearAll = () => {
@@ -14966,7 +14994,7 @@ var useTimers = () => {
14966
14994
  };
14967
14995
  };
14968
14996
  // src/angular/preserveAcrossHmr.ts
14969
- import { ChangeDetectorRef, inject as inject4 } from "@angular/core";
14997
+ import { ChangeDetectorRef, inject as inject5 } from "@angular/core";
14970
14998
 
14971
14999
  // src/angular/hmrPreserveCore.ts
14972
15000
  var isHmrPreserveDev = () => {
@@ -15037,15 +15065,15 @@ var preserveAcrossHmr = (instance, key) => {
15037
15065
  if (!restored)
15038
15066
  return;
15039
15067
  try {
15040
- const cdr = inject4(ChangeDetectorRef, { optional: true });
15068
+ const cdr = inject5(ChangeDetectorRef, { optional: true });
15041
15069
  if (cdr)
15042
15070
  queueMicrotask(() => cdr.markForCheck());
15043
15071
  } catch {}
15044
15072
  };
15045
15073
  // src/angular/pendingTask.ts
15046
- import { inject as inject5, PendingTasks } from "@angular/core";
15074
+ import { inject as inject6, PendingTasks } from "@angular/core";
15047
15075
  var withPendingTask = async (work) => {
15048
- const removeTask = inject5(PendingTasks).add();
15076
+ const removeTask = inject6(PendingTasks).add();
15049
15077
  try {
15050
15078
  return await work();
15051
15079
  } finally {
@@ -15245,7 +15273,7 @@ import {
15245
15273
  ChangeDetectorRef as ChangeDetectorRef2,
15246
15274
  Component as Component2,
15247
15275
  Input as Input2,
15248
- inject as inject6,
15276
+ inject as inject7,
15249
15277
  signal as signal2
15250
15278
  } from "@angular/core";
15251
15279
  import { DomSanitizer } from "@angular/platform-browser";
@@ -15262,8 +15290,8 @@ class StreamSlotComponent {
15262
15290
  constructor() {
15263
15291
  this.fallbackHtml = "";
15264
15292
  }
15265
- cdr = inject6(ChangeDetectorRef2);
15266
- sanitizer = inject6(DomSanitizer);
15293
+ cdr = inject7(ChangeDetectorRef2);
15294
+ sanitizer = inject7(DomSanitizer);
15267
15295
  slotConsumer = (payload) => {
15268
15296
  this.currentHtml.set(this.sanitizer.bypassSecurityTrustHtml(resolvePayloadHtml(payload)));
15269
15297
  this.cdr.markForCheck();
@@ -15351,6 +15379,7 @@ export {
15351
15379
  useTimers,
15352
15380
  useSubscription,
15353
15381
  useResource,
15382
+ usePageContext,
15354
15383
  renderIsland,
15355
15384
  provideDeterministicEnv,
15356
15385
  preserveAcrossHmr,
@@ -15368,5 +15397,5 @@ export {
15368
15397
  ABSOLUTE_HTTP_TRANSFER_CACHE_SKIP_HEADER
15369
15398
  };
15370
15399
 
15371
- //# debugId=D0855BF600604B6564756E2164756E21
15400
+ //# debugId=611222AD0534104464756E2164756E21
15372
15401
  //# sourceMappingURL=index.js.map