@absolutejs/absolute 0.20.0-beta.4 → 0.20.0-beta.40

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 (109) hide show
  1. package/README.md +200 -0
  2. package/dist/angular/browser.js +15 -1
  3. package/dist/angular/browser.js.map +3 -3
  4. package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
  5. package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
  6. package/dist/angular/index.js +361 -30
  7. package/dist/angular/index.js.map +9 -6
  8. package/dist/angular/server.js +361 -30
  9. package/dist/angular/server.js.map +9 -6
  10. package/dist/build.js +2093 -1114
  11. package/dist/build.js.map +20 -16
  12. package/dist/cli/config/server.js +4 -0
  13. package/dist/cli/index.js +6235 -1278
  14. package/dist/dev/client/cssUtils.ts +16 -2
  15. package/dist/dev/client/handlers/rebuild.ts +11 -1
  16. package/dist/dev/client/hmrClient.ts +35 -3
  17. package/dist/dev/client/hmrTiming.ts +16 -7
  18. package/dist/dev/client/syncDevtools.ts +237 -0
  19. package/dist/dev/serverBootstrap.js +28 -0
  20. package/dist/index.js +2925 -1670
  21. package/dist/index.js.map +37 -31
  22. package/dist/mobile/browser.js +123 -1
  23. package/dist/mobile/browser.js.map +6 -4
  24. package/dist/mobile/index.js +4185 -294
  25. package/dist/mobile/index.js.map +38 -18
  26. package/dist/mobile/remoteMacAgentEntry.js +14 -14
  27. package/dist/mobile/shellAuth.js +36 -0
  28. package/dist/mobile/shellBootstrap.js +837 -0
  29. package/dist/mobile/shellExpoDevices.js +99 -0
  30. package/dist/mobile/shellSync.js +173 -0
  31. package/dist/react/index.js +5 -1
  32. package/dist/react/index.js.map +3 -3
  33. package/dist/react/server.js +5 -1
  34. package/dist/react/server.js.map +3 -3
  35. package/dist/src/angular/pageHandler.d.ts +3 -0
  36. package/dist/src/build/pwa.d.ts +16 -0
  37. package/dist/src/cli/config/server.d.ts +1 -1
  38. package/dist/src/cli/instanceStatus.d.ts +1 -0
  39. package/dist/src/cli/scripts/dev.d.ts +2 -0
  40. package/dist/src/core/devBuild.d.ts +1 -0
  41. package/dist/src/core/pageHandlers.d.ts +11 -2
  42. package/dist/src/core/prepare.d.ts +376 -0
  43. package/dist/src/dev/clientManager.d.ts +1 -0
  44. package/dist/src/dev/devCert.d.ts +6 -4
  45. package/dist/src/dev/serverEntryCopies.d.ts +3 -0
  46. package/dist/src/mobile/androidEmulatorController.d.ts +14 -2
  47. package/dist/src/mobile/androidRelease.d.ts +6 -0
  48. package/dist/src/mobile/androidTestReport.d.ts +14 -0
  49. package/dist/src/mobile/androidUpgradeConformance.d.ts +47 -0
  50. package/dist/src/mobile/androidWebView.d.ts +1 -0
  51. package/dist/src/mobile/browser.d.ts +1 -0
  52. package/dist/src/mobile/buildPipeline.d.ts +1 -0
  53. package/dist/src/mobile/capacitorBundle.d.ts +22 -1
  54. package/dist/src/mobile/ciWorkflow.d.ts +26 -0
  55. package/dist/src/mobile/client.d.ts +4 -0
  56. package/dist/src/mobile/config.d.ts +4 -1
  57. package/dist/src/mobile/devDeviceAdapter.d.ts +3 -0
  58. package/dist/src/mobile/deviceCapabilities.d.ts +46 -0
  59. package/dist/src/mobile/expoBridge.d.ts +91 -0
  60. package/dist/src/mobile/expoProject.d.ts +16 -0
  61. package/dist/src/mobile/index.d.ts +13 -0
  62. package/dist/src/mobile/iosDeviceAcceptance.d.ts +32 -0
  63. package/dist/src/mobile/iosPhysicalDeviceTransport.d.ts +16 -0
  64. package/dist/src/mobile/iosRelease.d.ts +4 -1
  65. package/dist/src/mobile/iosSimulatorController.d.ts +20 -2
  66. package/dist/src/mobile/iosTestReport.d.ts +24 -0
  67. package/dist/src/mobile/mobileBundleInspection.d.ts +55 -0
  68. package/dist/src/mobile/mobileInspect.d.ts +136 -0
  69. package/dist/src/mobile/mobilePreview.d.ts +174 -0
  70. package/dist/src/mobile/mobilePreviewClient.d.ts +1 -0
  71. package/dist/src/mobile/nativeAuth.d.ts +17 -0
  72. package/dist/src/mobile/nativeBackgroundSync.d.ts +4 -0
  73. package/dist/src/mobile/nativeDeviceCapabilities.d.ts +6 -0
  74. package/dist/src/mobile/nativeTestReport.d.ts +91 -0
  75. package/dist/src/mobile/releaseArtifact.d.ts +2 -0
  76. package/dist/src/mobile/releaseDoctor.d.ts +23 -1
  77. package/dist/src/mobile/remoteMacProtocol.d.ts +11 -0
  78. package/dist/src/mobile/shellAuth.d.ts +15 -0
  79. package/dist/src/mobile/shellBootstrap.d.ts +23 -1
  80. package/dist/src/mobile/shellExpoDevices.d.ts +3 -0
  81. package/dist/src/mobile/shellHttp.d.ts +2 -0
  82. package/dist/src/mobile/shellPush.d.ts +11 -0
  83. package/dist/src/mobile/shellSync.d.ts +47 -0
  84. package/dist/src/mobile/staticDocument.d.ts +5 -0
  85. package/dist/src/mobile/syncRemediation.d.ts +10 -0
  86. package/dist/src/mobile/syncSchema.d.ts +9 -0
  87. package/dist/src/mobile/transport.d.ts +16 -1
  88. package/dist/src/plugins/hmr.d.ts +3 -0
  89. package/dist/src/plugins/imageOptimizer.d.ts +1 -1
  90. package/dist/src/react/hooks/useMediaQuery.d.ts +1 -1
  91. package/dist/src/svelte/pageHandler.d.ts +3 -0
  92. package/dist/src/utils/imageProcessing.d.ts +3 -0
  93. package/dist/src/utils/loadConfig.d.ts +1 -0
  94. package/dist/src/utils/logger.d.ts +1 -0
  95. package/dist/src/utils/startupBanner.d.ts +1 -0
  96. package/dist/src/utils/userAgentFunctions.d.ts +1 -1
  97. package/dist/src/vue/pageHandler.d.ts +3 -0
  98. package/dist/svelte/index.js +316 -23
  99. package/dist/svelte/index.js.map +8 -5
  100. package/dist/svelte/server.js +311 -18
  101. package/dist/svelte/server.js.map +8 -5
  102. package/dist/types/build.d.ts +50 -3
  103. package/dist/types/cli.d.ts +1 -0
  104. package/dist/types/messages.d.ts +1 -1
  105. package/dist/vue/index.js +316 -23
  106. package/dist/vue/index.js.map +8 -5
  107. package/dist/vue/server.js +311 -18
  108. package/dist/vue/server.js.map +8 -5
  109. package/package.json +41 -11
@@ -3281,7 +3281,7 @@ var SLOT_ID_PREFIX = "abs-slot-", CLOSING_BODY_TAG = "</body>", CLOSING_HEAD_TAG
3281
3281
  getStreamingSlotsRuntimeScript()
3282
3282
  ].filter(Boolean).join(";");
3283
3283
  return `<script${createNonceAttr(nonce)}>${escapeScriptContent(runtimeBody)}</script>`;
3284
- }, toUint8 = (value, encoder) => encoder.encode(value), isRecord4 = (value) => Boolean(value) && typeof value === "object", isSafeHtmlLike = (value) => isRecord4(value) && typeof value.changingThisBreaksApplicationSecurity === "string", normalizeSafeHtml = (value) => {
3284
+ }, toUint8 = (value, encoder) => encoder.encode(value), isRecord5 = (value) => Boolean(value) && typeof value === "object", isSafeHtmlLike = (value) => isRecord5(value) && typeof value.changingThisBreaksApplicationSecurity === "string", normalizeSafeHtml = (value) => {
3285
3285
  if (isSafeHtmlLike(value)) {
3286
3286
  return value.changingThisBreaksApplicationSecurity;
3287
3287
  }
@@ -3342,7 +3342,7 @@ var SLOT_ID_PREFIX = "abs-slot-", CLOSING_BODY_TAG = "</body>", CLOSING_HEAD_TAG
3342
3342
  }, createTimeoutError = (slot, timeoutMs) => {
3343
3343
  const error = Object.assign(new Error(`Streaming slot "${slot.id}" timed out after ${timeoutMs}ms`), { __absTimeout: true });
3344
3344
  return error;
3345
- }, isSlotPatchPayloadObject = (value) => isRecord4(value) && ("html" in value), isTimeoutError = (error) => isRecord4(error) && error.__absTimeout === true, toStreamingSlot = (slot, policy) => ({
3345
+ }, isSlotPatchPayloadObject = (value) => isRecord5(value) && ("html" in value), isTimeoutError = (error) => isRecord5(error) && error.__absTimeout === true, toStreamingSlot = (slot, policy) => ({
3346
3346
  errorHtml: slot.errorHtml === undefined ? policy.errorHtml : slot.errorHtml,
3347
3347
  fallbackHtml: normalizeSlotText(slot.fallbackHtml, policy.fallbackHtml),
3348
3348
  id: slot.id ?? createStreamingSlotId(),
@@ -3854,6 +3854,7 @@ var colors, MONTHS, formatTimestamp = () => {
3854
3854
  port,
3855
3855
  host,
3856
3856
  networkUrl,
3857
+ mobilePreviewUrl,
3857
3858
  protocol = "http"
3858
3859
  } = options;
3859
3860
  const name = `${colors.cyan}${colors.bold}ABSOLUTEJS${colors.reset}`;
@@ -3867,6 +3868,9 @@ var colors, MONTHS, formatTimestamp = () => {
3867
3868
  if (networkUrl) {
3868
3869
  console.log(` ${colors.green}\u279C${colors.reset} ${colors.bold}Network:${colors.reset} ${networkUrl}`);
3869
3870
  }
3871
+ if (mobilePreviewUrl) {
3872
+ console.log(` ${colors.green}\u279C${colors.reset} ${colors.bold}Mobile:${colors.reset} ${mobilePreviewUrl}`);
3873
+ }
3870
3874
  console.log("");
3871
3875
  };
3872
3876
  var init_startupBanner = __esm(() => {
@@ -4537,7 +4541,15 @@ import { existsSync as existsSync5, readFileSync as readFileSync5, promises as f
4537
4541
  import { join as join9, basename as basename4, sep, dirname as dirname5, resolve as resolve7, relative as relative5 } from "path";
4538
4542
  var {Glob } = globalThis.Bun;
4539
4543
  import ts from "typescript";
4540
- var traceAngularPhase = async (name, fn, metadata) => {
4544
+ var atomicWriteSequence = 0, writeTextFileAtomically = async (path, content) => {
4545
+ const temporaryPath = `${path}.tmp.${process.pid}.${atomicWriteSequence++}`;
4546
+ try {
4547
+ await fs.writeFile(temporaryPath, content, "utf-8");
4548
+ await fs.rename(temporaryPath, path);
4549
+ } finally {
4550
+ await fs.rm(temporaryPath, { force: true });
4551
+ }
4552
+ }, traceAngularPhase = async (name, fn, metadata) => {
4541
4553
  const tracePhase = globalThis.__absoluteBuildTracePhase;
4542
4554
  return tracePhase ? tracePhase(`compile/angular/${name}`, fn, metadata) : await fn();
4543
4555
  }, readTsconfigPathAliases = () => {
@@ -4803,10 +4815,10 @@ var traceAngularPhase = async (name, fn, metadata) => {
4803
4815
  }
4804
4816
  }, writeResourceCacheFile = async (cachePath, source) => {
4805
4817
  await fs.mkdir(dirname5(cachePath), { recursive: true });
4806
- await fs.writeFile(cachePath, JSON.stringify({
4818
+ await writeTextFileAtomically(cachePath, JSON.stringify({
4807
4819
  source,
4808
4820
  version: 1
4809
- }), "utf-8");
4821
+ }));
4810
4822
  }, resolveResourceTransformCachePath = async (filePath, source, stylePreprocessors) => {
4811
4823
  const resourcePaths = collectAngularResourcePaths(source, dirname5(filePath));
4812
4824
  const resourceContents = await Promise.all(resourcePaths.map(async (resourcePath) => {
@@ -4992,7 +5004,7 @@ var traceAngularPhase = async (name, fn, metadata) => {
4992
5004
  });
4993
5005
  await traceAngularPhase("aot/write-output", () => Promise.all(entries.map(async ({ target, content }) => {
4994
5006
  await fs.mkdir(dirname5(target), { recursive: true });
4995
- await fs.writeFile(target, content, "utf-8");
5007
+ await writeTextFileAtomically(target, content);
4996
5008
  })), { outputs: entries.length });
4997
5009
  return await traceAngularPhase("aot/collect-output-paths", () => entries.map(({ target }) => target), { outputs: entries.length });
4998
5010
  }, compileAngularFile = async (inputPath, outDir, stylePreprocessors) => compileAngularFiles([inputPath], outDir, stylePreprocessors), jitContentCache, invalidateAngularJitCache = (filePath) => {
@@ -5457,7 +5469,7 @@ ${fields}
5457
5469
  const processedContent = transpileAndRewrite(sourceCode, relativeDir, actualPath, importRewrites);
5458
5470
  const preservedInjection = await readPreservedInjection(targetPath);
5459
5471
  await fs.mkdir(targetDir, { recursive: true });
5460
- await fs.writeFile(targetPath, processedContent + preservedInjection, "utf-8");
5472
+ await writeTextFileAtomically(targetPath, processedContent + preservedInjection);
5461
5473
  jitContentCache.set(cacheKey, contentHash);
5462
5474
  }
5463
5475
  allOutputs.push(targetPath);
@@ -5473,7 +5485,7 @@ ${fields}
5473
5485
  export const __ABSOLUTE_PAGE_USES_LEGACY_ANIMATIONS__ = true;
5474
5486
  ` : withoutLegacyFlag;
5475
5487
  if (nextEntryOutput !== entryOutput) {
5476
- await fs.writeFile(entryOutputPath, nextEntryOutput, "utf-8");
5488
+ await writeTextFileAtomically(entryOutputPath, nextEntryOutput);
5477
5489
  }
5478
5490
  }
5479
5491
  return allOutputs;
@@ -5643,7 +5655,7 @@ export const providers = [${fragments.join(", ")}];
5643
5655
  `;
5644
5656
  }
5645
5657
  }
5646
- await traceAngularPhase("wrapper/write-server-output", () => fs.writeFile(rawServerFile, rewritten, "utf-8"), { entry: resolvedEntry });
5658
+ await traceAngularPhase("wrapper/write-server-output", () => writeTextFileAtomically(rawServerFile, rewritten), { entry: resolvedEntry });
5647
5659
  const relativePath = relative5(indexesDir, rawServerFile).replace(/\\/g, "/");
5648
5660
  const normalizedImportPath = relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
5649
5661
  const hmrPreamble = hmr ? `window.__HMR_FRAMEWORK__ = "angular";
@@ -5667,6 +5679,7 @@ var requestContext = Object.prototype.hasOwnProperty.call(window, '__ABS_ANGULAR
5667
5679
  var pageHasIslands = Boolean(pageModule.__ABSOLUTE_PAGE_HAS_ISLANDS__) || Boolean(document.querySelector('[data-island="true"]'));
5668
5680
  var pageHasRawStreamingSlots = Boolean(document.querySelector('[data-absolute-raw-slot="true"]'));
5669
5681
  var pageHasStreamingSlots = Boolean(document.querySelector('[data-absolute-slot="true"]'));
5682
+ var isClientRender = window.__ABSOLUTE_PAGE_RENDER_MODE__ === 'client';
5670
5683
  var contextProviders = [{ provide: REQUEST_CONTEXT, useValue: requestContext }];
5671
5684
  // Page-level providers are injected directly into the page module's
5672
5685
  // server output by \`compileAngular\`'s providers-injection step
@@ -5717,13 +5730,14 @@ if (!document.querySelector(_sel)) {
5717
5730
  }
5718
5731
 
5719
5732
  var providers = [provideZonelessChangeDetection()];
5720
- if (!window.__HMR_SKIP_HYDRATION__ && !pageHasIslands) {
5733
+ if (!isClientRender && !window.__HMR_SKIP_HYDRATION__ && !pageHasIslands) {
5721
5734
  providers.push(provideClientHydration(withHttpTransferCacheOptions(absoluteHttpTransferCacheOptions)));
5722
5735
  }
5723
5736
  delete window.__HMR_SKIP_HYDRATION__;
5724
5737
  providers.push.apply(providers, pageProviders);
5725
5738
  providers.push.apply(providers, contextProviders);
5726
5739
  window.__ABS_SLOT_HYDRATION_PENDING__ = pageHasRawStreamingSlots;
5740
+ var absolutePageReady = Promise.resolve();
5727
5741
 
5728
5742
  if (pageHasRawStreamingSlots) {
5729
5743
  window.__ABS_SLOT_HYDRATION_PENDING__ = false;
@@ -5733,7 +5747,7 @@ if (pageHasRawStreamingSlots) {
5733
5747
  });
5734
5748
  }
5735
5749
  } else {
5736
- bootstrapApplication(${componentClassName}, {
5750
+ absolutePageReady = bootstrapApplication(${componentClassName}, {
5737
5751
  providers: providers
5738
5752
  }).then(function (appRef) {
5739
5753
  window.__ANGULAR_APP__ = appRef;
@@ -5743,8 +5757,17 @@ if (pageHasRawStreamingSlots) {
5743
5757
  window.__ABS_SLOT_FLUSH__();
5744
5758
  });
5745
5759
  }
5760
+ return appRef;
5746
5761
  });
5747
5762
  }
5763
+ window.__ABSOLUTE_PAGE_READY__ = absolutePageReady;
5764
+ window.__ABSOLUTE_PAGE_DISPOSE__ = async function() {
5765
+ await absolutePageReady;
5766
+ if (window.__ANGULAR_APP__) {
5767
+ window.__ANGULAR_APP__.destroy();
5768
+ window.__ANGULAR_APP__ = null;
5769
+ }
5770
+ };
5748
5771
  `.trim() : `
5749
5772
  import '@angular/compiler';
5750
5773
  import { bootstrapApplication } from '@angular/platform-browser';
@@ -5763,6 +5786,7 @@ var requestContext = Object.prototype.hasOwnProperty.call(window, '__ABS_ANGULAR
5763
5786
  var pageHasIslands = Boolean(pageModule.__ABSOLUTE_PAGE_HAS_ISLANDS__) || Boolean(document.querySelector('[data-island="true"]'));
5764
5787
  var pageHasRawStreamingSlots = Boolean(document.querySelector('[data-absolute-raw-slot="true"]'));
5765
5788
  var pageHasStreamingSlots = Boolean(document.querySelector('[data-absolute-slot="true"]'));
5789
+ var isClientRender = window.__ABSOLUTE_PAGE_RENDER_MODE__ === 'client';
5766
5790
  var contextProviders = [{ provide: REQUEST_CONTEXT, useValue: requestContext }];
5767
5791
  // Page-level providers are injected directly into the page module's
5768
5792
  // server output by \`compileAngular\`'s providers-injection step
@@ -5782,11 +5806,21 @@ var absoluteHttpTransferCacheOptions = {
5782
5806
 
5783
5807
  enableProdMode();
5784
5808
 
5809
+ // Production mobile/client-only activation starts from AbsoluteJS's empty
5810
+ // #root shell rather than server-rendered Angular markup. Create the page's
5811
+ // actual Angular host from its compiled selector so application authors do
5812
+ // not need framework-specific mobile configuration.
5813
+ var _sel = ${componentClassName}.\u0275cmp?.selectors?.[0]?.[0] || 'ng-app';
5814
+ if (!document.querySelector(_sel)) {
5815
+ (document.getElementById('root') || document.body).appendChild(document.createElement(_sel));
5816
+ }
5817
+
5785
5818
  var providers = [provideZonelessChangeDetection()].concat(pageProviders).concat(contextProviders);
5786
- if (!pageHasIslands) {
5819
+ if (!isClientRender && !pageHasIslands) {
5787
5820
  providers.unshift(provideClientHydration(withHttpTransferCacheOptions(absoluteHttpTransferCacheOptions)));
5788
5821
  }
5789
5822
  window.__ABS_SLOT_HYDRATION_PENDING__ = pageHasRawStreamingSlots;
5823
+ var absolutePageReady = Promise.resolve();
5790
5824
 
5791
5825
  if (pageHasRawStreamingSlots) {
5792
5826
  window.__ABS_SLOT_HYDRATION_PENDING__ = false;
@@ -5796,7 +5830,7 @@ if (pageHasRawStreamingSlots) {
5796
5830
  });
5797
5831
  }
5798
5832
  } else {
5799
- bootstrapApplication(${componentClassName}, {
5833
+ absolutePageReady = bootstrapApplication(${componentClassName}, {
5800
5834
  providers: providers
5801
5835
  }).then(function (appRef) {
5802
5836
  window.__ANGULAR_APP__ = appRef;
@@ -5806,12 +5840,21 @@ if (pageHasRawStreamingSlots) {
5806
5840
  window.__ABS_SLOT_FLUSH__();
5807
5841
  });
5808
5842
  }
5843
+ return appRef;
5809
5844
  });
5810
5845
  }
5846
+ window.__ABSOLUTE_PAGE_READY__ = absolutePageReady;
5847
+ window.__ABSOLUTE_PAGE_DISPOSE__ = async function() {
5848
+ await absolutePageReady;
5849
+ if (window.__ANGULAR_APP__) {
5850
+ window.__ANGULAR_APP__.destroy();
5851
+ window.__ANGULAR_APP__ = null;
5852
+ }
5853
+ };
5811
5854
  `.trim();
5812
5855
  const indexHash = Bun.hash(hydration).toString(BASE_36_RADIX);
5813
5856
  const indexUnchanged = cachedWrapper?.indexHash === indexHash;
5814
- await traceAngularPhase("wrapper/write-client-index", () => fs.writeFile(clientFile, hydration, "utf-8"), { entry: resolvedEntry });
5857
+ await traceAngularPhase("wrapper/write-client-index", () => writeTextFileAtomically(clientFile, hydration), { entry: resolvedEntry });
5815
5858
  wrapperOutputCache.set(resolvedEntry, {
5816
5859
  indexHash,
5817
5860
  serverHash: serverContentHash
@@ -6008,7 +6051,7 @@ var provideDeterministicEnv = (options = {}) => {
6008
6051
  };
6009
6052
  // src/angular/pageHandler.ts
6010
6053
  init_constants();
6011
- import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
6054
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
6012
6055
  import { lstat, mkdir as mkdir4, readlink, symlink } from "fs/promises";
6013
6056
  import { basename as basename5, dirname as dirname6, join as join10, resolve as resolve8 } from "path";
6014
6057
  import { pathToFileURL as pathToFileURL2 } from "url";
@@ -6401,6 +6444,276 @@ var lowerAngularServerIslands = async (html) => {
6401
6444
  // src/angular/pageHandler.ts
6402
6445
  init_devRouteRegistrationCallsite();
6403
6446
 
6447
+ // src/core/requestContext.ts
6448
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
6449
+ import { Elysia as Elysia2 } from "elysia";
6450
+ var REQUEST_STORAGE_KEY = Symbol.for("absolutejs.requestAsyncLocalStorage");
6451
+ var isAbsoluteRequestStorage = (value) => typeof value === "object" && value !== null && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function";
6452
+ var getRequestStorage = () => {
6453
+ const value = Reflect.get(globalThis, REQUEST_STORAGE_KEY);
6454
+ return isAbsoluteRequestStorage(value) ? value : undefined;
6455
+ };
6456
+ var ensureRequestStorage = () => {
6457
+ const existing = getRequestStorage();
6458
+ if (existing)
6459
+ return existing;
6460
+ const storage = new AsyncLocalStorage2;
6461
+ Reflect.set(globalThis, REQUEST_STORAGE_KEY, storage);
6462
+ return storage;
6463
+ };
6464
+ var absoluteRequestContext = new Elysia2({
6465
+ name: "absolutejs-request-context"
6466
+ }).request(({ request }) => {
6467
+ ensureRequestStorage().enterWith({ request });
6468
+ }).as("global");
6469
+ var getCurrentAbsoluteRequest = () => getRequestStorage()?.getStore()?.request;
6470
+ var runWithAbsoluteRequest = (request, callback) => ensureRequestStorage().run({ request }, callback);
6471
+
6472
+ // src/mobile/producerContextState.ts
6473
+ var ABSOLUTE_MOBILE_PRODUCER_STORAGE_KEY = Symbol.for("absolutejs.mobileProducerAsyncLocalStorage");
6474
+ var frameworks = new Set([
6475
+ "angular",
6476
+ "ember",
6477
+ "html",
6478
+ "htmx",
6479
+ "react",
6480
+ "svelte",
6481
+ "vue"
6482
+ ]);
6483
+ var isCompatibilityPage = (value) => typeof value === "object" && value !== null && ("bundleHash" in value) && typeof value.bundleHash === "string" && ("contract" in value) && typeof value.contract === "string" && ("framework" in value) && typeof value.framework === "string" && frameworks.has(value.framework) && ("pageId" in value) && typeof value.pageId === "string" && ("propsSchemaHash" in value) && typeof value.propsSchemaHash === "string";
6484
+ var getCurrentAbsoluteMobileProducerContext = () => {
6485
+ const value = Reflect.get(globalThis, ABSOLUTE_MOBILE_PRODUCER_STORAGE_KEY);
6486
+ if (typeof value !== "object" || value === null || !("getStore" in value) || typeof value.getStore !== "function") {
6487
+ return;
6488
+ }
6489
+ const context = value.getStore();
6490
+ if (typeof context !== "object" || context === null || !("page" in context) || !isCompatibilityPage(context.page) || !("releaseId" in context) || typeof context.releaseId !== "string") {
6491
+ return;
6492
+ }
6493
+ return { page: context.page, releaseId: context.releaseId };
6494
+ };
6495
+
6496
+ // src/mobile/pageProtocol.ts
6497
+ var ABSOLUTE_MOBILE_PAGE_MEDIA_TYPE = "application/vnd.absolute.page+json";
6498
+ var ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION = 1;
6499
+ var BAD_REQUEST_STATUS = 400;
6500
+ var OK_STATUS = 200;
6501
+ var SERVER_ERROR_STATUS = 500;
6502
+ var UPGRADE_REQUIRED_STATUS = 426;
6503
+ var MOBILE_PAGE_REQUEST_HEADERS = {
6504
+ appBuild: "x-absolute-mobile-app-build",
6505
+ pageBundle: "x-absolute-mobile-page-bundle",
6506
+ pageContracts: "x-absolute-mobile-page-contracts",
6507
+ pageId: "x-absolute-mobile-page-id",
6508
+ protocol: "x-absolute-mobile-protocol",
6509
+ runtime: "x-absolute-mobile-runtime"
6510
+ };
6511
+ var parseMediaType = (value) => value.split(";", 1)[0]?.trim().toLowerCase();
6512
+ var acceptsAbsoluteMobilePage = (request) => {
6513
+ if (!request)
6514
+ return false;
6515
+ return (request.headers.get("accept") ?? "").split(",").some((value) => parseMediaType(value) === ABSOLUTE_MOBILE_PAGE_MEDIA_TYPE);
6516
+ };
6517
+ var readRequiredHeader = (request, name) => {
6518
+ const value = request.headers.get(name)?.trim();
6519
+ return value ? value : undefined;
6520
+ };
6521
+ var parseAbsoluteMobilePageRequest = (request) => {
6522
+ if (!request || !acceptsAbsoluteMobilePage(request)) {
6523
+ return { kind: "not-mobile" };
6524
+ }
6525
+ const protocolValue = readRequiredHeader(request, MOBILE_PAGE_REQUEST_HEADERS.protocol);
6526
+ const runtime = readRequiredHeader(request, MOBILE_PAGE_REQUEST_HEADERS.runtime);
6527
+ const appBuild = readRequiredHeader(request, MOBILE_PAGE_REQUEST_HEADERS.appBuild);
6528
+ const pageBundle = readRequiredHeader(request, MOBILE_PAGE_REQUEST_HEADERS.pageBundle);
6529
+ const pageContractsValue = readRequiredHeader(request, MOBILE_PAGE_REQUEST_HEADERS.pageContracts);
6530
+ const pageId = readRequiredHeader(request, MOBILE_PAGE_REQUEST_HEADERS.pageId);
6531
+ if (!protocolValue || !/^\d+$/.test(protocolValue)) {
6532
+ return {
6533
+ kind: "invalid",
6534
+ message: `Missing or invalid ${MOBILE_PAGE_REQUEST_HEADERS.protocol} header.`
6535
+ };
6536
+ }
6537
+ if (!runtime) {
6538
+ return {
6539
+ kind: "invalid",
6540
+ message: `Missing ${MOBILE_PAGE_REQUEST_HEADERS.runtime} header.`
6541
+ };
6542
+ }
6543
+ if (!appBuild) {
6544
+ return {
6545
+ kind: "invalid",
6546
+ message: `Missing ${MOBILE_PAGE_REQUEST_HEADERS.appBuild} header.`
6547
+ };
6548
+ }
6549
+ if (!pageBundle) {
6550
+ return {
6551
+ kind: "invalid",
6552
+ message: `Missing ${MOBILE_PAGE_REQUEST_HEADERS.pageBundle} header.`
6553
+ };
6554
+ }
6555
+ if (!pageContractsValue) {
6556
+ return {
6557
+ kind: "invalid",
6558
+ message: `Missing ${MOBILE_PAGE_REQUEST_HEADERS.pageContracts} header.`
6559
+ };
6560
+ }
6561
+ if (!pageId) {
6562
+ return {
6563
+ kind: "invalid",
6564
+ message: `Missing ${MOBILE_PAGE_REQUEST_HEADERS.pageId} header.`
6565
+ };
6566
+ }
6567
+ const pageContracts = [
6568
+ ...new Set(pageContractsValue.split(",").map((value) => value.trim()).filter(Boolean))
6569
+ ];
6570
+ if (pageContracts.length === 0) {
6571
+ return {
6572
+ kind: "invalid",
6573
+ message: `${MOBILE_PAGE_REQUEST_HEADERS.pageContracts} must contain at least one contract.`
6574
+ };
6575
+ }
6576
+ return {
6577
+ client: {
6578
+ appBuild,
6579
+ pageBundle,
6580
+ pageContracts,
6581
+ pageId,
6582
+ protocol: Number(protocolValue),
6583
+ runtime
6584
+ },
6585
+ kind: "mobile"
6586
+ };
6587
+ };
6588
+ var responseHeaders = () => {
6589
+ const headers = new Headers({
6590
+ "cache-control": "no-store",
6591
+ "content-type": `${ABSOLUTE_MOBILE_PAGE_MEDIA_TYPE}; version=${ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION}`
6592
+ });
6593
+ headerVaryValues.forEach((value) => headers.append("vary", value));
6594
+ return headers;
6595
+ };
6596
+ var headerVaryValues = [
6597
+ "Accept",
6598
+ MOBILE_PAGE_REQUEST_HEADERS.protocol,
6599
+ MOBILE_PAGE_REQUEST_HEADERS.runtime,
6600
+ MOBILE_PAGE_REQUEST_HEADERS.appBuild,
6601
+ MOBILE_PAGE_REQUEST_HEADERS.pageBundle,
6602
+ MOBILE_PAGE_REQUEST_HEADERS.pageContracts,
6603
+ MOBILE_PAGE_REQUEST_HEADERS.pageId
6604
+ ];
6605
+ var envelopeResponse = (response, status) => new Response(JSON.stringify({
6606
+ protocol: ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION,
6607
+ response
6608
+ }), { headers: responseHeaders(), status });
6609
+ var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
6610
+ var normalizeJsonValue = (value) => {
6611
+ const serialized = JSON.stringify(value);
6612
+ if (serialized === undefined) {
6613
+ throw new TypeError("Mobile page props must be JSON-serializable.");
6614
+ }
6615
+ const parsed = JSON.parse(serialized);
6616
+ if (!isRecord4(parsed)) {
6617
+ throw new TypeError("Mobile page props must serialize to an object.");
6618
+ }
6619
+ return parsed;
6620
+ };
6621
+ var finalizeArchivedMobilePage = (context, input) => {
6622
+ const { page } = context;
6623
+ if (page.pageId !== input.compatibility.pageId || page.framework !== input.compatibility.framework) {
6624
+ return envelopeResponse({
6625
+ kind: "invalid-request",
6626
+ message: "Archived producer page identity does not match its release artifact."
6627
+ }, BAD_REQUEST_STATUS);
6628
+ }
6629
+ try {
6630
+ const [currentRepresentation] = input.compatibility.representations;
6631
+ if (!currentRepresentation) {
6632
+ throw new TypeError("Mobile page has no current representation.");
6633
+ }
6634
+ return envelopeResponse({
6635
+ contract: page.contract,
6636
+ framework: page.framework,
6637
+ kind: "page",
6638
+ pageId: page.pageId,
6639
+ props: normalizeJsonValue(currentRepresentation.mapProps(input.props)),
6640
+ status: input.status ?? OK_STATUS
6641
+ }, input.status ?? OK_STATUS);
6642
+ } catch (error) {
6643
+ console.error(`[Mobile] Archived producer ${context.releaseId} failed for ${page.pageId}:`, error);
6644
+ return createAbsoluteMobilePageErrorResponse(page.pageId);
6645
+ }
6646
+ };
6647
+ var createAbsoluteMobileInvalidRequestResponse = (message) => envelopeResponse({ kind: "invalid-request", message }, BAD_REQUEST_STATUS);
6648
+ var createAbsoluteMobilePageErrorResponse = (pageId) => envelopeResponse({
6649
+ code: "representation-failed",
6650
+ kind: "error",
6651
+ pageId,
6652
+ status: SERVER_ERROR_STATUS
6653
+ }, SERVER_ERROR_STATUS);
6654
+ var createAbsoluteMobileUpgradeResponse = (result) => envelopeResponse(result, UPGRADE_REQUIRED_STATUS);
6655
+ var finalizeAbsoluteMobilePage = (input) => {
6656
+ const parsed = parseAbsoluteMobilePageRequest(input.request);
6657
+ if (parsed.kind === "not-mobile")
6658
+ return;
6659
+ if (parsed.kind === "invalid") {
6660
+ return envelopeResponse({ kind: "invalid-request", message: parsed.message }, BAD_REQUEST_STATUS);
6661
+ }
6662
+ const { client } = parsed;
6663
+ if (client.pageId !== input.compatibility.pageId) {
6664
+ return envelopeResponse({
6665
+ kind: "invalid-request",
6666
+ message: `Requested mobile page ${client.pageId} does not match ${input.compatibility.pageId}.`
6667
+ }, BAD_REQUEST_STATUS);
6668
+ }
6669
+ const producerContext = getCurrentAbsoluteMobileProducerContext();
6670
+ if (producerContext)
6671
+ return finalizeArchivedMobilePage(producerContext, input);
6672
+ if (client.protocol !== ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION) {
6673
+ return envelopeResponse({
6674
+ kind: "upgrade-required",
6675
+ pageId: input.compatibility.pageId,
6676
+ reason: "protocol"
6677
+ }, UPGRADE_REQUIRED_STATUS);
6678
+ }
6679
+ if (!input.compatibility.runtimes.includes(client.runtime)) {
6680
+ return envelopeResponse({
6681
+ kind: "upgrade-required",
6682
+ pageId: input.compatibility.pageId,
6683
+ reason: "runtime",
6684
+ supportedRuntimes: [...input.compatibility.runtimes]
6685
+ }, UPGRADE_REQUIRED_STATUS);
6686
+ }
6687
+ const clientContracts = new Set(client.pageContracts);
6688
+ const representation = input.compatibility.representations.find(({ contract }) => clientContracts.has(contract));
6689
+ if (!representation) {
6690
+ return envelopeResponse({
6691
+ kind: "upgrade-required",
6692
+ pageId: input.compatibility.pageId,
6693
+ reason: "page-contract",
6694
+ supportedContracts: input.compatibility.representations.map(({ contract }) => contract)
6695
+ }, UPGRADE_REQUIRED_STATUS);
6696
+ }
6697
+ try {
6698
+ return envelopeResponse({
6699
+ contract: representation.contract,
6700
+ framework: input.compatibility.framework,
6701
+ kind: "page",
6702
+ pageId: input.compatibility.pageId,
6703
+ props: normalizeJsonValue(representation.mapProps(input.props)),
6704
+ status: input.status ?? OK_STATUS
6705
+ }, input.status ?? OK_STATUS);
6706
+ } catch (error) {
6707
+ console.error(`[Mobile] Failed to produce ${input.compatibility.pageId} representation ${representation.contract}:`, error);
6708
+ return envelopeResponse({
6709
+ code: "representation-failed",
6710
+ kind: "error",
6711
+ pageId: input.compatibility.pageId,
6712
+ status: SERVER_ERROR_STATUS
6713
+ }, SERVER_ERROR_STATUS);
6714
+ }
6715
+ };
6716
+
6404
6717
  // src/angular/ssrSanitizer.ts
6405
6718
  var escapeHtml2 = (str) => String(str).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
6406
6719
  var bypassValue = (value) => ({
@@ -6512,7 +6825,7 @@ var withRegisteredStreamingSlots = async (renderResponse, options = {}) => {
6512
6825
 
6513
6826
  // src/core/streamingSlotWarningScope.ts
6514
6827
  init_logger();
6515
- import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
6828
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
6516
6829
  var STREAMING_SLOT_WARNING_STORAGE_KEY2 = Symbol.for("absolutejs.streamingSlotWarningAsyncLocalStorage");
6517
6830
  var isObjectRecord4 = (value) => Boolean(value) && typeof value === "object";
6518
6831
  var isAsyncLocalStorage3 = (value) => isObjectRecord4(value) && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function";
@@ -6528,7 +6841,7 @@ var ensureWarningStorage = () => {
6528
6841
  if (existing) {
6529
6842
  return existing;
6530
6843
  }
6531
- const storage = new AsyncLocalStorage2;
6844
+ const storage = new AsyncLocalStorage3;
6532
6845
  Reflect.set(globalThis, STREAMING_SLOT_WARNING_STORAGE_KEY2, storage);
6533
6846
  return storage;
6534
6847
  };
@@ -6570,11 +6883,11 @@ var runWithStreamingSlotWarningScope = (task, metadata) => ensureWarningStorage(
6570
6883
 
6571
6884
  // src/angular/pageHandler.ts
6572
6885
  init_ssrRender();
6573
- var isRecord5 = (value) => typeof value === "object" && value !== null;
6886
+ var isRecord6 = (value) => typeof value === "object" && value !== null;
6574
6887
  var isAngularComponent2 = (value) => typeof value === "function";
6575
6888
  var componentHostsRouterOutlet = (component) => {
6576
6889
  const componentDef = Reflect.get(component, "\u0275cmp");
6577
- if (!isRecord5(componentDef))
6890
+ if (!isRecord6(componentDef))
6578
6891
  return false;
6579
6892
  const rawDependencies = componentDef.dependencies;
6580
6893
  const dependencies = typeof rawDependencies === "function" ? Reflect.apply(rawDependencies, undefined, []) : rawDependencies;
@@ -6584,7 +6897,7 @@ var componentHostsRouterOutlet = (component) => {
6584
6897
  if (dependency === null || typeof dependency !== "object" && typeof dependency !== "function")
6585
6898
  return false;
6586
6899
  const directiveDef = Reflect.get(dependency, "\u0275dir") ?? dependency;
6587
- if (!isRecord5(directiveDef))
6900
+ if (!isRecord6(directiveDef))
6588
6901
  return false;
6589
6902
  const { selectors } = directiveDef;
6590
6903
  return Array.isArray(selectors) && JSON.stringify(selectors).includes("router-outlet");
@@ -6614,7 +6927,7 @@ var ensureAngularCompiler = () => {
6614
6927
  }
6615
6928
  return compilerImportPromise;
6616
6929
  };
6617
- var readAngularPageModule = (value) => isRecord5(value) ? value : null;
6930
+ var readAngularPageModule = (value) => isRecord6(value) ? value : null;
6618
6931
  var resolveAngularSsrOutDir = (projectRoot = process.cwd(), configuredOutDir = process.env.ABSOLUTE_ANGULAR_SSR_OUTDIR) => configuredOutDir ?? join10(projectRoot, ".absolutejs", "runtime", "angular-ssr");
6619
6932
  var createAngularRuntimeCacheBuster = () => `${Date.now().toString(BASE_36_RADIX)}.${Math.random().toString(BASE_36_RADIX).substring(2, RANDOM_ID_END_INDEX)}`;
6620
6933
  var existingNodeModulesLinkMatches = async (nodeModulesLink, expectedTarget) => {
@@ -6715,14 +7028,32 @@ var resolveRequestRenderUrl = (request) => {
6715
7028
  return "/";
6716
7029
  }
6717
7030
  };
6718
- var angularSsrContext = new AsyncLocalStorage3;
7031
+ var angularSsrContext = new AsyncLocalStorage4;
6719
7032
  setSsrContextGetter(() => angularSsrContext.getStore());
6720
7033
  var handleAngularPageRequest = async (input) => {
6721
7034
  const requestId = `angular_${Date.now()}_${Math.random().toString(BASE_36_RADIX).substring(2, RANDOM_ID_END_INDEX)}`;
7035
+ const request = input.request ?? getCurrentAbsoluteRequest();
7036
+ const pageId = input.__absoluteMobile?.pageId ?? derivePageName(input.pagePath);
7037
+ const currentContract = input.__absoluteMobile?.contract ?? `angular:${pageId}:${ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION}`;
7038
+ const mobileResponse = finalizeAbsoluteMobilePage({
7039
+ compatibility: {
7040
+ framework: "angular",
7041
+ pageId,
7042
+ representations: [
7043
+ { contract: currentContract, mapProps: (props) => props }
7044
+ ],
7045
+ runtimes: [String(ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION)]
7046
+ },
7047
+ props: isRecord6(input.requestContext) ? input.requestContext : Object.create(null),
7048
+ request,
7049
+ status: input.responseInit?.status
7050
+ });
7051
+ if (mobileResponse)
7052
+ return mobileResponse;
6722
7053
  return angularSsrContext.run(requestId, async () => {
6723
- const spaNotFound = await renderSpaNotFound("angular", derivePageName(input.pagePath), input.request);
7054
+ const spaNotFound = await renderSpaNotFound("angular", derivePageName(input.pagePath), request);
6724
7055
  if (spaNotFound)
6725
- return withPageCacheHeaders(spaNotFound, input.request);
7056
+ return withPageCacheHeaders(spaNotFound, request);
6726
7057
  await ensureAngularCompiler();
6727
7058
  const userHeadTag = input.headTag ?? "<head></head>";
6728
7059
  const resolvedIndexPath = input.indexPath;
@@ -6730,7 +7061,7 @@ var handleAngularPageRequest = async (input) => {
6730
7061
  const resolvedPagePath = input.pagePath;
6731
7062
  const maybeRequestContext = input.requestContext;
6732
7063
  const responseInit = input.responseInit ?? {};
6733
- const resolvedUrl = resolveRequestRenderUrl(input.request);
7064
+ const resolvedUrl = resolveRequestRenderUrl(request);
6734
7065
  const siblingCss = await readSiblingCss(resolvedPagePath);
6735
7066
  const resolvedHeadTag = injectInlineCss(userHeadTag, siblingCss);
6736
7067
  cacheRouteData(resolvedPagePath, {
@@ -6767,7 +7098,7 @@ var handleAngularPageRequest = async (input) => {
6767
7098
  ...handlerCallProviders,
6768
7099
  ...await buildServerAnimationProviders(usesLegacyAnimations)
6769
7100
  ];
6770
- const providers = buildProviders(deps, sanitizer, input.request, maybeRequestContext, responseInit, combinedProviders);
7101
+ const providers = buildProviders(deps, sanitizer, request, maybeRequestContext, responseInit, combinedProviders);
6771
7102
  const rawHtml = await renderAngularApp(deps, PageComponent, providers, htmlString, resolvedUrl);
6772
7103
  const shouldProcessIslands = hasIslands || rawHtml.includes("<absolute-island");
6773
7104
  const htmlWithLoweredIslands = shouldProcessIslands ? await lowerAngularServerIslands(rawHtml) : rawHtml;
@@ -6775,18 +7106,18 @@ var handleAngularPageRequest = async (input) => {
6775
7106
  return new Response(html, withHtmlContentType(responseInit));
6776
7107
  };
6777
7108
  const pageResponse = await runWithStreamingSlotWarningScope(() => options?.collectStreamingSlots === true ? withRegisteredStreamingSlots(renderPageResponse, options) : renderPageResponse(), { handlerCallsite });
6778
- return withPageCacheHeaders(pageResponse, input.request);
7109
+ return withPageCacheHeaders(pageResponse, request);
6779
7110
  } catch (error) {
6780
7111
  console.error("[SSR] Angular render error:", error);
6781
7112
  const pageName = derivePageName(resolvedPagePath);
6782
7113
  const conventionResponse = await renderConventionError("angular", pageName, error);
6783
7114
  if (conventionResponse) {
6784
- return withPageCacheHeaders(conventionResponse, input.request);
7115
+ return withPageCacheHeaders(conventionResponse, request);
6785
7116
  }
6786
7117
  return withPageCacheHeaders(new Response(ssrErrorPage("angular", error), {
6787
7118
  headers: { "Content-Type": "text/html" },
6788
7119
  status: 500
6789
- }), input.request);
7120
+ }), request);
6790
7121
  }
6791
7122
  });
6792
7123
  };
@@ -6812,5 +7143,5 @@ export {
6812
7143
  ABSOLUTE_HTTP_TRANSFER_CACHE_SKIP_HEADER
6813
7144
  };
6814
7145
 
6815
- //# debugId=61E1DD96B8611B8364756E2164756E21
7146
+ //# debugId=E479518984C3318364756E2164756E21
6816
7147
  //# sourceMappingURL=server.js.map