@absolutejs/absolute 0.19.0-beta.999 → 0.20.0-beta.1
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.
- package/LICENSE +21 -13
- package/README.md +48 -2
- package/dist/angular/browser.js +82 -77
- package/dist/angular/browser.js.map +11 -11
- package/dist/angular/components/constants.js +43 -0
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/angular/hmrPreserveCore.ts +132 -134
- package/dist/angular/index.js +1719 -844
- package/dist/angular/index.js.map +34 -26
- package/dist/angular/server.js +1620 -768
- package/dist/angular/server.js.map +28 -20
- package/dist/build.js +4935 -2593
- package/dist/build.js.map +72 -57
- package/dist/cli/config/client.js +578 -0
- package/dist/cli/config/server.js +39587 -0
- package/dist/cli/htmx/htmx.min.js +1 -0
- package/dist/cli/index.js +16828 -3511
- package/dist/client/index.js +49 -46
- package/dist/client/index.js.map +12 -12
- package/dist/core/streamingSlotRegistrar.js +1 -19
- package/dist/core/streamingSlotRegistrar.js.map +2 -2
- package/dist/core/streamingSlotRegistry.js +1 -19
- package/dist/core/streamingSlotRegistry.js.map +2 -2
- package/dist/dev/client/cssUtils.ts +98 -41
- package/dist/dev/client/domState.ts +2 -0
- package/dist/dev/client/errorOverlay.ts +14 -13
- package/dist/dev/client/handlers/angularHmrShim.ts +20 -20
- package/dist/dev/client/handlers/angularRemount.ts +74 -55
- package/dist/dev/client/handlers/angularRemountWiring.ts +1 -2
- package/dist/dev/client/handlers/html.ts +144 -41
- package/dist/dev/client/handlers/htmx.ts +43 -8
- package/dist/dev/client/handlers/react.ts +114 -32
- package/dist/dev/client/handlers/rebuild.ts +28 -8
- package/dist/dev/client/handlers/svelte.ts +92 -51
- package/dist/dev/client/handlers/vue.ts +36 -45
- package/dist/dev/client/hmrClient.ts +101 -26
- package/dist/dev/client/hmrTiming.ts +141 -0
- package/dist/dev/client/hmrToast.ts +22 -24
- package/dist/dev/client/reactRefreshSetup.ts +4 -0
- package/dist/dev/client/vendor/reactRefreshRuntime.d.ts +12 -0
- package/dist/dev/client/vendor/reactRefreshRuntime.js +313 -0
- package/dist/dev/serverBootstrap.js +45 -0
- package/dist/index.js +7153 -3224
- package/dist/index.js.map +118 -86
- package/dist/islands/browser.js +1 -19
- package/dist/islands/browser.js.map +3 -3
- package/dist/islands/index.js +709 -120
- package/dist/islands/index.js.map +18 -13
- package/dist/mobile/browser.js +428 -0
- package/dist/mobile/browser.js.map +12 -0
- package/dist/mobile/index.js +3058 -0
- package/dist/mobile/index.js.map +35 -0
- package/dist/react/browser.js +13 -62
- package/dist/react/browser.js.map +5 -6
- package/dist/react/components/browser/index.js +23 -13
- package/dist/react/components/index.js +30 -34
- package/dist/react/components/index.js.map +8 -7
- package/dist/react/hooks/index.js +1 -19
- package/dist/react/hooks/index.js.map +3 -3
- package/dist/react/index.js +1643 -679
- package/dist/react/index.js.map +29 -20
- package/dist/react/jsxDevRuntimeCompat.js +22 -20
- package/dist/react/jsxDevRuntimeCompat.js.map +5 -4
- package/dist/react/jsxRuntimeCompat.js +90 -0
- package/dist/react/jsxRuntimeCompat.js.map +10 -0
- package/dist/react/router/browser.js +77 -0
- package/dist/react/router/browser.js.map +10 -0
- package/dist/react/router/index.js +77 -0
- package/dist/react/router/index.js.map +10 -0
- package/dist/react/server.js +950 -565
- package/dist/react/server.js.map +16 -11
- package/dist/src/angular/components/constants.d.ts +21 -0
- package/dist/src/angular/hmrPreserveCore.d.ts +7 -20
- package/dist/src/angular/islands.d.ts +1 -1
- package/dist/src/angular/pageHandler.d.ts +2 -0
- package/dist/src/angular/ssrRender.d.ts +4 -1
- package/dist/src/build/bunStringRawUnicodePlugin.d.ts +12 -0
- package/dist/src/build/chainInlineSourcemaps.d.ts +1 -0
- package/dist/src/build/compileAngular.d.ts +5 -7
- package/dist/src/build/compileSvelte.d.ts +3 -0
- package/dist/src/build/compileVue.d.ts +3 -1
- package/dist/src/build/generateReactIndexes.d.ts +1 -0
- package/dist/src/build/islandRegistryTransform.d.ts +17 -0
- package/dist/src/build/maskLiterals.d.ts +28 -0
- package/dist/src/build/parseVueSpaRoutes.d.ts +5 -0
- package/dist/src/build/resolveBuildMode.d.ts +7 -0
- package/dist/src/build/serverExternals.d.ts +14 -0
- package/dist/src/build/spaSideManifests.d.ts +16 -0
- package/dist/src/build/tailwindCompiler.d.ts +0 -1
- package/dist/src/cli/add/dependencies.d.ts +13 -0
- package/dist/src/cli/config/absolute/AbsoluteConfigPanel.d.ts +6 -0
- package/dist/src/cli/config/absolute/editAbsoluteConfig.d.ts +5 -0
- package/dist/src/cli/config/absolute/resolveAbsoluteConfig.d.ts +19 -0
- package/dist/src/cli/config/auth/AuthPanel.d.ts +6 -0
- package/dist/src/cli/config/auth/authCatalog.d.ts +10 -0
- package/dist/src/cli/config/auth/authScaffolds.d.ts +16 -0
- package/dist/src/cli/config/auth/editAuthConfig.d.ts +5 -0
- package/dist/src/cli/config/auth/resolveAuthSettings.d.ts +14 -0
- package/dist/src/cli/config/auth/resolveAuthState.d.ts +2 -0
- package/dist/src/cli/config/auth/scaffoldAuthFeature.d.ts +6 -0
- package/dist/src/cli/config/client.d.ts +1 -0
- package/dist/src/cli/config/configCert.d.ts +12 -0
- package/dist/src/cli/config/eslint/EslintPanel.d.ts +6 -0
- package/dist/src/cli/config/eslint/configAst.d.ts +18 -0
- package/dist/src/cli/config/eslint/editConfigRule.d.ts +6 -0
- package/dist/src/cli/config/eslint/eslintStyles.d.ts +1 -0
- package/dist/src/cli/config/eslint/resolveConfig.d.ts +3 -0
- package/dist/src/cli/config/eslint/serializeValue.d.ts +9 -0
- package/dist/src/cli/config/guards.d.ts +4 -0
- package/dist/src/cli/config/integrations/IntegrationsPanel.d.ts +6 -0
- package/dist/src/cli/config/packageJson/PackageJsonPanel.d.ts +6 -0
- package/dist/src/cli/config/packageJson/editPackageJson.d.ts +9 -0
- package/dist/src/cli/config/packageJson/resolvePackageJson.d.ts +8 -0
- package/dist/src/cli/config/page/ConfigShell.d.ts +6 -0
- package/dist/src/cli/config/page/FieldEditor.d.ts +9 -0
- package/dist/src/cli/config/page/PanelHost.d.ts +6 -0
- package/dist/src/cli/config/page/configStyles.d.ts +1 -0
- package/dist/src/cli/config/panels.d.ts +7 -0
- package/dist/src/cli/config/prettier/PrettierPanel.d.ts +6 -0
- package/dist/src/cli/config/prettier/editPrettier.d.ts +5 -0
- package/dist/src/cli/config/prettier/resolvePrettier.d.ts +11 -0
- package/dist/src/cli/config/schema/fromJsonSchema.d.ts +3 -0
- package/dist/src/cli/config/schema/fromType.d.ts +1 -0
- package/dist/src/cli/config/schema/serialize.d.ts +1 -0
- package/dist/src/cli/config/server.d.ts +527 -0
- package/dist/src/cli/config/tsconfig/TsconfigPanel.d.ts +6 -0
- package/dist/src/cli/config/tsconfig/editTsconfig.d.ts +5 -0
- package/dist/src/cli/config/tsconfig/resolveTsconfig.d.ts +8 -0
- package/dist/src/cli/config/tsconfig/tsconfigStyles.d.ts +1 -0
- package/dist/src/cli/discoverInstances.d.ts +5 -0
- package/dist/src/cli/elysiaOpenApiTypeboxPlugin.d.ts +8 -0
- package/dist/src/cli/generate/componentTemplates.d.ts +7 -0
- package/dist/src/cli/generate/context.d.ts +30 -0
- package/dist/src/cli/generate/cssStrategy.d.ts +20 -0
- package/dist/src/cli/generate/frameworkKey.d.ts +3 -0
- package/dist/src/cli/generate/frameworks.d.ts +40 -0
- package/dist/src/cli/generate/generateApi.d.ts +3 -0
- package/dist/src/cli/generate/generateComponent.d.ts +4 -0
- package/dist/src/cli/generate/generatePage.d.ts +4 -0
- package/dist/src/cli/generate/naming.d.ts +5 -0
- package/dist/src/cli/generate/navData.d.ts +10 -0
- package/dist/src/cli/generate/outcome.d.ts +17 -0
- package/dist/src/cli/generate/pageTemplates.d.ts +11 -0
- package/dist/src/cli/generate/routeWiring.d.ts +40 -0
- package/dist/src/cli/generate/staticNav.d.ts +5 -0
- package/dist/src/cli/heapDiff.d.ts +1 -0
- package/dist/src/cli/htmx/install.d.ts +6 -0
- package/dist/src/cli/inspectData.d.ts +12 -0
- package/dist/src/cli/inspectTui.d.ts +1 -0
- package/dist/src/cli/instanceStatus.d.ts +22 -0
- package/dist/src/cli/integrations/addPlugin.d.ts +8 -0
- package/dist/src/cli/integrations/catalog.d.ts +20 -0
- package/dist/src/cli/psTui.d.ts +1 -0
- package/dist/src/cli/scripts/add.d.ts +1 -0
- package/dist/src/cli/scripts/analyze.d.ts +1 -0
- package/dist/src/cli/scripts/api.d.ts +1 -0
- package/dist/src/cli/scripts/build.d.ts +1 -1
- package/dist/src/cli/scripts/db.d.ts +20 -0
- package/dist/src/cli/scripts/dev.d.ts +5 -1
- package/dist/src/cli/scripts/doctor.d.ts +1 -0
- package/dist/src/cli/scripts/env.d.ts +7 -0
- package/dist/src/cli/scripts/eslint.d.ts +37 -2
- package/dist/src/cli/scripts/eslintChunked.d.ts +37 -0
- package/dist/src/cli/scripts/generate.d.ts +1 -0
- package/dist/src/cli/scripts/htmx.d.ts +1 -0
- package/dist/src/cli/scripts/inspect.d.ts +1 -0
- package/dist/src/cli/scripts/islands.d.ts +1 -0
- package/dist/src/cli/scripts/lintProof.d.ts +42 -0
- package/dist/src/cli/scripts/logs.d.ts +1 -0
- package/dist/src/cli/scripts/ls.d.ts +1 -0
- package/dist/src/cli/scripts/mem.d.ts +1 -0
- package/dist/src/cli/scripts/mobile.d.ts +1 -0
- package/dist/src/cli/scripts/prettier.d.ts +2 -0
- package/dist/src/cli/scripts/ps.d.ts +1 -0
- package/dist/src/cli/scripts/remove.d.ts +1 -0
- package/dist/src/cli/scripts/routes.d.ts +1 -0
- package/dist/src/cli/scripts/start.d.ts +6 -1
- package/dist/src/cli/scripts/tunnelRelay.d.ts +9 -0
- package/dist/src/cli/scripts/workspace.d.ts +3 -1
- package/dist/src/cli/serverBundleExternals.d.ts +2 -0
- package/dist/src/cli/tuiPrimitives.d.ts +14 -0
- package/dist/src/cli/typeGraphCoherence.d.ts +32 -0
- package/dist/src/cli/utils.d.ts +3 -1
- package/dist/src/cli/workspaceTui.d.ts +2 -1
- package/dist/src/client/hydrators/react.d.ts +1 -1
- package/dist/src/client/hydrators/svelte.d.ts +1 -1
- package/dist/src/client/hydrators/vue.d.ts +1 -1
- package/dist/src/client/islandStore.d.ts +3 -3
- package/dist/src/client/preserveIslandMarkup.d.ts +4 -1
- package/dist/src/constants.d.ts +21 -0
- package/dist/src/core/angularServerModule.d.ts +1 -0
- package/dist/src/core/build.d.ts +11 -3
- package/dist/src/core/devRouteRegistrationCallsite.d.ts +1 -5
- package/dist/src/core/index.d.ts +1 -0
- package/dist/src/core/pageResponseCache.d.ts +23 -0
- package/dist/src/core/prepare.d.ts +192 -154
- package/dist/src/core/requestContext.d.ts +18 -0
- package/dist/src/dev/angular/fastHmrCompiler.d.ts +5 -3
- package/dist/src/dev/angular/hmrCompiler.d.ts +1 -1
- package/dist/src/dev/angular/resolveOwningComponents.d.ts +1 -1
- package/dist/src/dev/clientManager.d.ts +10 -1
- package/dist/src/dev/configResolver.d.ts +2 -0
- package/dist/src/dev/moduleMapper.d.ts +1 -1
- package/dist/src/dev/moduleServer.d.ts +2 -1
- package/dist/src/dev/pathUtils.d.ts +1 -1
- package/dist/src/dev/reactComponentClassifier.d.ts +1 -1
- package/dist/src/dev/rebuildTrigger.d.ts +4 -0
- package/dist/src/dev/requestInspector.d.ts +31 -0
- package/dist/src/dev/serverBootstrap.d.ts +1 -0
- package/dist/src/dev/serverEntryWatcher.d.ts +3 -3
- package/dist/src/dev/tunnel/client.d.ts +20 -0
- package/dist/src/dev/tunnel/protocol.d.ts +85 -0
- package/dist/src/dev/tunnel/relay.d.ts +28 -0
- package/dist/src/dev/webSocket.d.ts +1 -1
- package/dist/src/mobile/androidConformance.d.ts +42 -0
- package/dist/src/mobile/androidEmulatorController.d.ts +99 -0
- package/dist/src/mobile/androidNativeWatcher.d.ts +19 -0
- package/dist/src/mobile/androidRelease.d.ts +47 -0
- package/dist/src/mobile/androidWebView.d.ts +46 -0
- package/dist/src/mobile/artifactStore.d.ts +47 -0
- package/dist/src/mobile/associationFiles.d.ts +49 -0
- package/dist/src/mobile/browser.d.ts +2 -0
- package/dist/src/mobile/buildMetadata.d.ts +10 -0
- package/dist/src/mobile/buildPipeline.d.ts +8 -0
- package/dist/src/mobile/buildRelease.d.ts +24 -0
- package/dist/src/mobile/capacitorBundle.d.ts +28 -0
- package/dist/src/mobile/capacitorProject.d.ts +9 -0
- package/dist/src/mobile/client.d.ts +35 -0
- package/dist/src/mobile/compatibilityDispatcher.d.ts +26 -0
- package/dist/src/mobile/config.d.ts +16 -0
- package/dist/src/mobile/emulatorDoctor.d.ts +25 -0
- package/dist/src/mobile/emulatorInstaller.d.ts +41 -0
- package/dist/src/mobile/index.d.ts +19 -0
- package/dist/src/mobile/materializedBundle.d.ts +36 -0
- package/dist/src/mobile/nativeDeepLinks.d.ts +5 -0
- package/dist/src/mobile/pageProtocol.d.ts +89 -0
- package/dist/src/mobile/producerContext.d.ts +4 -0
- package/dist/src/mobile/producerContextState.d.ts +10 -0
- package/dist/src/mobile/releaseArtifact.d.ts +75 -0
- package/dist/src/mobile/releaseDoctor.d.ts +13 -0
- package/dist/src/mobile/routeMatcher.d.ts +3 -0
- package/dist/src/mobile/routeMetadataTransform.d.ts +13 -0
- package/dist/src/mobile/shellBootstrap.d.ts +1 -0
- package/dist/src/mobile/transport.d.ts +31 -0
- package/dist/src/plugins/devtoolsJson.d.ts +6 -47
- package/dist/src/plugins/hmr.d.ts +22 -96
- package/dist/src/plugins/imageOptimizer.d.ts +150 -62
- package/dist/src/plugins/networking.d.ts +2 -2
- package/dist/src/plugins/openApiPlugin.d.ts +4 -0
- package/dist/src/plugins/telemetryPlugin.d.ts +36 -0
- package/dist/src/react/browser.d.ts +0 -2
- package/dist/src/react/hooks/useMediaQuery.d.ts +1 -1
- package/dist/src/react/index.d.ts +0 -2
- package/dist/src/react/jsxDevRuntimeCompat.d.ts +1 -1
- package/dist/src/react/jsxRuntimeCompat.d.ts +7 -0
- package/dist/src/react/pageHandler.d.ts +8 -0
- package/dist/src/react/router/UniversalRouter.d.ts +43 -0
- package/dist/src/react/router/browser.d.ts +2 -0
- package/dist/src/react/router/index.d.ts +2 -0
- package/dist/src/svelte/pageHandler.d.ts +5 -0
- package/dist/src/svelte/router/hashMode.d.ts +1 -6
- package/dist/src/svelte/router/matchPath.d.ts +4 -24
- package/dist/src/svelte/router/page.svelte.d.ts +1 -10
- package/dist/src/svelte/router/prefetchCache.d.ts +2 -6
- package/dist/src/utils/cleanup.d.ts +1 -0
- package/dist/src/utils/defineConvention.d.ts +2 -2
- package/dist/src/utils/defineEnv.d.ts +4 -4
- package/dist/src/utils/formatBytes.d.ts +2 -0
- package/dist/src/utils/generatedDir.d.ts +1 -1
- package/dist/src/utils/iconVersion.d.ts +5 -0
- package/dist/src/utils/imageProcessing.d.ts +1 -1
- package/dist/src/utils/index.d.ts +2 -0
- package/dist/src/utils/inlinePageCss.d.ts +9 -0
- package/dist/src/utils/instanceRegistry.d.ts +13 -0
- package/dist/src/utils/isTestSourcePath.d.ts +1 -0
- package/dist/src/utils/jsonLd.d.ts +1 -1
- package/dist/src/utils/loadConfig.d.ts +11 -3
- package/dist/src/utils/logger.d.ts +2 -0
- package/dist/src/utils/portScan.d.ts +22 -0
- package/dist/src/utils/projectRoot.d.ts +17 -0
- package/dist/src/utils/resolveConvention.d.ts +1 -1
- package/dist/src/utils/resolveDevPort.d.ts +4 -1
- package/dist/src/utils/runtimeMode.d.ts +1 -1
- package/dist/src/utils/spaRouteCss.d.ts +10 -0
- package/dist/src/utils/spaRouteManifest.d.ts +8 -0
- package/dist/src/utils/stripStringsAndComments.d.ts +18 -0
- package/dist/src/utils/userAgentFunctions.d.ts +1 -1
- package/dist/src/utils/vueCompiler.d.ts +1 -0
- package/dist/src/vue/components/Image.d.ts +2 -2
- package/dist/src/vue/defineVuePage.d.ts +1 -11
- package/dist/src/vue/index.d.ts +3 -0
- package/dist/src/vue/pageHandler.d.ts +5 -0
- package/dist/src/vue/resolveGeneratedVueModulePath.d.ts +1 -0
- package/dist/src/vue/teleports.d.ts +2 -0
- package/dist/src/vue/useResource.d.ts +65 -0
- package/dist/svelte/browser.js +1 -19
- package/dist/svelte/browser.js.map +3 -3
- package/dist/svelte/components/Head.svelte +7 -1
- package/dist/svelte/index.js +1281 -543
- package/dist/svelte/index.js.map +27 -19
- package/dist/svelte/router/Link.svelte.d.ts +3 -3
- package/dist/svelte/router/Route.svelte.d.ts +5 -5
- package/dist/svelte/router/Router.svelte.d.ts +3 -3
- package/dist/svelte/router/hashMode.ts +6 -12
- package/dist/svelte/router/matchPath.ts +44 -61
- package/dist/svelte/router/page.d.ts +1 -10
- package/dist/svelte/router/page.js +6 -6
- package/dist/svelte/router/prefetchCache.ts +21 -23
- package/dist/svelte/router/viewTransitions.ts +22 -12
- package/dist/svelte/server.js +697 -565
- package/dist/svelte/server.js.map +14 -11
- package/dist/types/absoluteConfig.d.ts +22 -0
- package/dist/types/angular.d.ts +4 -1
- package/dist/types/authPanel.d.ts +62 -0
- package/dist/types/build.d.ts +116 -0
- package/dist/types/cli.d.ts +57 -0
- package/dist/types/config.d.ts +52 -0
- package/dist/types/eslintConfig.d.ts +68 -0
- package/dist/types/globals.d.ts +31 -10
- package/dist/types/image.d.ts +2 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/integrationsPanel.d.ts +29 -0
- package/dist/types/messages.d.ts +12 -0
- package/dist/types/packageJson.d.ts +74 -0
- package/dist/types/packageJsonPanel.d.ts +29 -0
- package/dist/types/prettier.d.ts +26 -0
- package/dist/types/tsconfig.d.ts +31 -0
- package/dist/types/vue.d.ts +13 -15
- package/dist/vue/browser.js +14 -36
- package/dist/vue/browser.js.map +5 -5
- package/dist/vue/components/Image.js +3 -20
- package/dist/vue/components/Image.js.map +3 -3
- package/dist/vue/components/index.js +3 -20
- package/dist/vue/components/index.js.map +3 -3
- package/dist/vue/index.js +1573 -620
- package/dist/vue/index.js.map +34 -22
- package/dist/vue/server.js +800 -520
- package/dist/vue/server.js.map +17 -11
- package/package.json +145 -68
- package/dist/src/react/UniversalRouter.d.ts +0 -12
|
@@ -9,43 +9,13 @@ import {
|
|
|
9
9
|
restoreScrollState
|
|
10
10
|
} from '../domState';
|
|
11
11
|
import { detectCurrentFramework, findIndexPath } from '../frameworkDetect';
|
|
12
|
+
import { sendAbsoluteHmrTiming } from '../hmrTiming';
|
|
13
|
+
import { swapCSSStylesheet } from '../cssUtils';
|
|
12
14
|
|
|
13
15
|
type SvelteHmrWindow = Window & {
|
|
14
16
|
__SVELTE_HMR_ACCEPT__?: Record<string, (mod: unknown) => void>;
|
|
15
17
|
};
|
|
16
18
|
|
|
17
|
-
/* Swap a stylesheet link by matching cssBaseName or framework name */
|
|
18
|
-
const swapStylesheet = (
|
|
19
|
-
cssUrl: string,
|
|
20
|
-
cssBaseName: string,
|
|
21
|
-
framework: string
|
|
22
|
-
) => {
|
|
23
|
-
let existingLink: HTMLLinkElement | null = null;
|
|
24
|
-
document
|
|
25
|
-
.querySelectorAll<HTMLLinkElement>('link[rel="stylesheet"]')
|
|
26
|
-
.forEach((link) => {
|
|
27
|
-
const href = link.getAttribute('href') ?? '';
|
|
28
|
-
if (href.includes(cssBaseName) || href.includes(framework)) {
|
|
29
|
-
existingLink = link;
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
if (!existingLink) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const capturedExisting: HTMLLinkElement = existingLink;
|
|
38
|
-
const newLink = document.createElement('link');
|
|
39
|
-
newLink.rel = 'stylesheet';
|
|
40
|
-
newLink.href = `${cssUrl}?t=${Date.now()}`;
|
|
41
|
-
newLink.onload = () => {
|
|
42
|
-
if (capturedExisting && capturedExisting.parentNode) {
|
|
43
|
-
capturedExisting.remove();
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
document.head.appendChild(newLink);
|
|
47
|
-
};
|
|
48
|
-
|
|
49
19
|
const extractCountFromDOM = () => {
|
|
50
20
|
const countButton = document.querySelector('button');
|
|
51
21
|
if (!countButton || !countButton.textContent) {
|
|
@@ -222,17 +192,27 @@ export const handleSvelteUpdate = (message: {
|
|
|
222
192
|
sourceFile?: string;
|
|
223
193
|
updateType?: string;
|
|
224
194
|
};
|
|
195
|
+
timestamp?: number;
|
|
225
196
|
}) => {
|
|
226
197
|
const svelteFrameworkCheck = detectCurrentFramework();
|
|
227
198
|
if (svelteFrameworkCheck !== 'svelte') return;
|
|
228
199
|
|
|
229
200
|
/* CSS-only update: hot-swap stylesheet, no remount needed */
|
|
230
201
|
if (message.data.updateType === 'css-only' && message.data.cssUrl) {
|
|
231
|
-
|
|
202
|
+
const clientStart = performance.now();
|
|
203
|
+
const cssBaseName = message.data.cssBaseName || '';
|
|
204
|
+
void swapCSSStylesheet(
|
|
232
205
|
message.data.cssUrl,
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
206
|
+
(href) => href.includes(cssBaseName) || href.includes('svelte')
|
|
207
|
+
).then((applied) => {
|
|
208
|
+
sendAbsoluteHmrTiming({
|
|
209
|
+
clientStart,
|
|
210
|
+
kind: 'css',
|
|
211
|
+
outcome: applied ? 'applied' : 'failed',
|
|
212
|
+
serverMs: message.data.serverDuration,
|
|
213
|
+
updateId: message.timestamp
|
|
214
|
+
});
|
|
215
|
+
});
|
|
236
216
|
|
|
237
217
|
return;
|
|
238
218
|
}
|
|
@@ -255,10 +235,10 @@ export const handleSvelteUpdate = (message: {
|
|
|
255
235
|
|
|
256
236
|
/* CSS pre-update: swap stylesheet BEFORE importing to prevent FOUC */
|
|
257
237
|
if (message.data.cssUrl) {
|
|
258
|
-
|
|
238
|
+
const cssBaseName = message.data.cssBaseName || '';
|
|
239
|
+
void swapCSSStylesheet(
|
|
259
240
|
message.data.cssUrl,
|
|
260
|
-
|
|
261
|
-
'svelte'
|
|
241
|
+
(href) => href.includes(cssBaseName) || href.includes('svelte')
|
|
262
242
|
);
|
|
263
243
|
}
|
|
264
244
|
|
|
@@ -273,32 +253,93 @@ export const handleSvelteUpdate = (message: {
|
|
|
273
253
|
const svelteWindow: SvelteHmrWindow = window;
|
|
274
254
|
const acceptRegistry = svelteWindow.__SVELTE_HMR_ACCEPT__;
|
|
275
255
|
|
|
276
|
-
// Save the OLD module's accept callback BEFORE importing.
|
|
277
|
-
|
|
256
|
+
// Save the OLD module's accept callback BEFORE importing. The exact
|
|
257
|
+
// key is the broadcast `pageModuleUrl`; on the happy path it matches
|
|
258
|
+
// the key the module server registered. If it doesn't (the registry
|
|
259
|
+
// was repopulated under a slightly different URL key, or `bun --hot`
|
|
260
|
+
// re-evaluated the module and reset `__SVELTE_HMR_ACCEPT__`), fall back
|
|
261
|
+
// to a suffix/basename match so we still find the callback. Exact match
|
|
262
|
+
// always wins, so the happy path is unchanged.
|
|
263
|
+
let acceptFn = acceptRegistry?.[pageModuleUrl];
|
|
264
|
+
if (!acceptFn && acceptRegistry) {
|
|
265
|
+
const wantBase = pageModuleUrl.split('?')[0] ?? pageModuleUrl;
|
|
266
|
+
const hit = Object.keys(acceptRegistry).find(
|
|
267
|
+
(key) =>
|
|
268
|
+
key === wantBase ||
|
|
269
|
+
key.endsWith(wantBase) ||
|
|
270
|
+
wantBase.endsWith(key)
|
|
271
|
+
);
|
|
272
|
+
if (hit) acceptFn = acceptRegistry[hit];
|
|
273
|
+
}
|
|
278
274
|
|
|
279
275
|
import(modulePath)
|
|
280
276
|
.then((newModule) => {
|
|
277
|
+
let applied = false;
|
|
281
278
|
if (acceptFn) {
|
|
282
279
|
acceptFn(newModule);
|
|
280
|
+
applied = true;
|
|
283
281
|
}
|
|
284
282
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
283
|
+
/* $.hmr_accept swaps component code in place but re-runs
|
|
284
|
+
* the <script> body with the original mount props, so any
|
|
285
|
+
* state seeded from a prop (e.g. a composable doing
|
|
286
|
+
* $state(initialCount)) resets. Remount with the preserved
|
|
287
|
+
* state merged into props — mirroring the bundled-fallback
|
|
288
|
+
* bootstrap — so that state carries across (issue #41). */
|
|
289
|
+
const preserved = window.__HMR_PRESERVED_STATE__;
|
|
290
|
+
const remount = window.__SVELTE_REMOUNT__;
|
|
291
|
+
const hasPreserved =
|
|
292
|
+
preserved && Object.keys(preserved).length > 0;
|
|
293
|
+
|
|
294
|
+
if (applied) {
|
|
295
|
+
if (typeof remount === 'function' && hasPreserved) {
|
|
296
|
+
remount({
|
|
297
|
+
...(window.__INITIAL_PROPS__ ?? {}),
|
|
298
|
+
...preserved
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
} else if (typeof remount === 'function') {
|
|
302
|
+
/* Resilience fallback: no accept callback was found, so
|
|
303
|
+
* `$.hmr` never wired the freshly imported module in. The
|
|
304
|
+
* import warmed the module cache; remount the page with
|
|
305
|
+
* merged props to actually apply the new code instead of
|
|
306
|
+
* silently doing nothing. */
|
|
307
|
+
remount({
|
|
308
|
+
...(window.__INITIAL_PROPS__ ?? {}),
|
|
309
|
+
...(preserved ?? {})
|
|
310
|
+
});
|
|
311
|
+
} else {
|
|
312
|
+
/* Last resort: nothing can apply the update in place. */
|
|
313
|
+
console.warn(
|
|
314
|
+
'[HMR] Svelte accept callback missing and no remount available; reloading'
|
|
295
315
|
);
|
|
316
|
+
window.__HMR_PRESERVED_STATE__ = undefined;
|
|
317
|
+
window.location.reload();
|
|
318
|
+
|
|
319
|
+
return undefined;
|
|
320
|
+
}
|
|
321
|
+
window.__HMR_PRESERVED_STATE__ = undefined;
|
|
322
|
+
|
|
323
|
+
if (message.data.serverDuration !== undefined) {
|
|
324
|
+
sendAbsoluteHmrTiming({
|
|
325
|
+
clientStart,
|
|
326
|
+
kind: 'component',
|
|
327
|
+
serverMs: message.data.serverDuration,
|
|
328
|
+
updateId: message.timestamp
|
|
329
|
+
});
|
|
296
330
|
}
|
|
297
331
|
|
|
298
332
|
return undefined;
|
|
299
333
|
})
|
|
300
334
|
.catch((err: unknown) => {
|
|
301
335
|
console.warn('[HMR] Svelte HMR failed, reloading:', err);
|
|
336
|
+
sendAbsoluteHmrTiming({
|
|
337
|
+
clientStart,
|
|
338
|
+
kind: 'component',
|
|
339
|
+
outcome: 'reloaded',
|
|
340
|
+
serverMs: message.data.serverDuration,
|
|
341
|
+
updateId: message.timestamp
|
|
342
|
+
});
|
|
302
343
|
window.location.reload();
|
|
303
344
|
});
|
|
304
345
|
|
|
@@ -4,6 +4,8 @@ import type {} from '../../../types/globals';
|
|
|
4
4
|
import type { VueComponentInstance, VueVNode } from '../../../types/vue';
|
|
5
5
|
import { saveDOMState, restoreDOMState } from '../domState';
|
|
6
6
|
import { detectCurrentFramework, findIndexPath } from '../frameworkDetect';
|
|
7
|
+
import { sendAbsoluteHmrTiming } from '../hmrTiming';
|
|
8
|
+
import { swapCSSStylesheet } from '../cssUtils';
|
|
7
9
|
|
|
8
10
|
/* Collect reactive value from a setup state entry into the target record */
|
|
9
11
|
const collectSetupValue = (
|
|
@@ -67,38 +69,6 @@ const extractChildComponentState = (
|
|
|
67
69
|
walkVNode(instance.subTree, state);
|
|
68
70
|
};
|
|
69
71
|
|
|
70
|
-
/* Find an existing stylesheet link matching the given base name */
|
|
71
|
-
const findMatchingStylesheetLink = (cssBaseName: string) => {
|
|
72
|
-
let found: HTMLLinkElement | null = null;
|
|
73
|
-
document
|
|
74
|
-
.querySelectorAll<HTMLLinkElement>('link[rel="stylesheet"]')
|
|
75
|
-
.forEach((link) => {
|
|
76
|
-
const href = link.getAttribute('href') ?? '';
|
|
77
|
-
if (cssBaseName && href.includes(cssBaseName)) {
|
|
78
|
-
found = link;
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
return found;
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
/* Swap a stylesheet link with a new one, removing the old on load */
|
|
86
|
-
const swapStylesheet = (cssUrl: string, cssBaseName: string) => {
|
|
87
|
-
const existingLink = findMatchingStylesheetLink(cssBaseName);
|
|
88
|
-
if (!existingLink) return;
|
|
89
|
-
|
|
90
|
-
const capturedExisting: HTMLLinkElement = existingLink;
|
|
91
|
-
const newLink = document.createElement('link');
|
|
92
|
-
newLink.rel = 'stylesheet';
|
|
93
|
-
newLink.href = `${cssUrl}?t=${Date.now()}`;
|
|
94
|
-
newLink.onload = function () {
|
|
95
|
-
if (capturedExisting && capturedExisting.parentNode) {
|
|
96
|
-
capturedExisting.remove();
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
document.head.appendChild(newLink);
|
|
100
|
-
};
|
|
101
|
-
|
|
102
72
|
/* Extract Vue reactive state from app instance */
|
|
103
73
|
const extractVueAppState = (vuePreservedState: Record<string, unknown>) => {
|
|
104
74
|
if (!window.__VUE_APP__ || !window.__VUE_APP__._instance) return;
|
|
@@ -163,12 +133,26 @@ export const handleVueUpdate = (message: {
|
|
|
163
133
|
sourceFile?: string;
|
|
164
134
|
updateType?: string;
|
|
165
135
|
};
|
|
136
|
+
timestamp?: number;
|
|
166
137
|
}) => {
|
|
167
138
|
const vueFrameworkCheck = detectCurrentFramework();
|
|
168
139
|
if (vueFrameworkCheck !== 'vue') return;
|
|
169
140
|
|
|
170
141
|
if (message.data.updateType === 'css-only' && message.data.cssUrl) {
|
|
171
|
-
|
|
142
|
+
const clientStart = performance.now();
|
|
143
|
+
const cssBaseName = message.data.cssBaseName || '';
|
|
144
|
+
void swapCSSStylesheet(
|
|
145
|
+
message.data.cssUrl,
|
|
146
|
+
(href) => Boolean(cssBaseName) && href.includes(cssBaseName)
|
|
147
|
+
).then((applied) => {
|
|
148
|
+
sendAbsoluteHmrTiming({
|
|
149
|
+
clientStart,
|
|
150
|
+
kind: 'css',
|
|
151
|
+
outcome: applied ? 'applied' : 'failed',
|
|
152
|
+
serverMs: message.data.serverDuration,
|
|
153
|
+
updateId: message.timestamp
|
|
154
|
+
});
|
|
155
|
+
});
|
|
172
156
|
|
|
173
157
|
return;
|
|
174
158
|
}
|
|
@@ -224,17 +208,13 @@ export const handleVueUpdate = (message: {
|
|
|
224
208
|
}
|
|
225
209
|
sessionStorage.removeItem('__HMR_ACTIVE__');
|
|
226
210
|
|
|
227
|
-
if (
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
);
|
|
234
|
-
const total = (message.data.serverDuration ?? 0) + clientMs;
|
|
235
|
-
window.__HMR_WS__.send(
|
|
236
|
-
JSON.stringify({ duration: total, type: 'hmr-timing' })
|
|
237
|
-
);
|
|
211
|
+
if (message.data.serverDuration !== undefined) {
|
|
212
|
+
sendAbsoluteHmrTiming({
|
|
213
|
+
clientStart,
|
|
214
|
+
kind: 'component',
|
|
215
|
+
serverMs: message.data.serverDuration,
|
|
216
|
+
updateId: message.timestamp
|
|
217
|
+
});
|
|
238
218
|
}
|
|
239
219
|
|
|
240
220
|
return undefined;
|
|
@@ -242,6 +222,13 @@ export const handleVueUpdate = (message: {
|
|
|
242
222
|
.catch((err: unknown) => {
|
|
243
223
|
console.warn('[HMR] Vue HMR failed, reloading:', err);
|
|
244
224
|
sessionStorage.removeItem('__HMR_ACTIVE__');
|
|
225
|
+
sendAbsoluteHmrTiming({
|
|
226
|
+
clientStart,
|
|
227
|
+
kind: 'component',
|
|
228
|
+
outcome: 'reloaded',
|
|
229
|
+
serverMs: message.data.serverDuration,
|
|
230
|
+
updateId: message.timestamp
|
|
231
|
+
});
|
|
245
232
|
window.location.reload();
|
|
246
233
|
});
|
|
247
234
|
|
|
@@ -250,7 +237,11 @@ export const handleVueUpdate = (message: {
|
|
|
250
237
|
|
|
251
238
|
/* CSS pre-update: swap stylesheet BEFORE unmounting to prevent FOUC */
|
|
252
239
|
if (message.data.cssUrl) {
|
|
253
|
-
|
|
240
|
+
const cssBaseName = message.data.cssBaseName || '';
|
|
241
|
+
void swapCSSStylesheet(
|
|
242
|
+
message.data.cssUrl,
|
|
243
|
+
(href) => Boolean(cssBaseName) && href.includes(cssBaseName)
|
|
244
|
+
);
|
|
254
245
|
}
|
|
255
246
|
|
|
256
247
|
/* Unmount old Vue app but keep DOM visually intact during async import.
|
|
@@ -12,6 +12,11 @@ import {
|
|
|
12
12
|
WEBSOCKET_NORMAL_CLOSURE
|
|
13
13
|
} from './constants';
|
|
14
14
|
import { detectCurrentFramework } from './frameworkDetect';
|
|
15
|
+
import {
|
|
16
|
+
absoluteHmrClientTarget,
|
|
17
|
+
restoreAbsoluteHmrApply,
|
|
18
|
+
sendAbsoluteHmrTiming
|
|
19
|
+
} from './hmrTiming';
|
|
15
20
|
import { hideErrorOverlay, showErrorOverlay } from './errorOverlay';
|
|
16
21
|
import {
|
|
17
22
|
dispatchAngularComponentRemount,
|
|
@@ -32,8 +37,54 @@ import {
|
|
|
32
37
|
handleRebuildError
|
|
33
38
|
} from './handlers/rebuild';
|
|
34
39
|
|
|
40
|
+
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
41
|
+
typeof value === 'object' && value !== null;
|
|
42
|
+
|
|
43
|
+
const isStringRecord = (value: unknown): value is Record<string, string> =>
|
|
44
|
+
isRecord(value) &&
|
|
45
|
+
Object.values(value).every((entry) => typeof entry === 'string');
|
|
46
|
+
|
|
47
|
+
restoreAbsoluteHmrApply();
|
|
48
|
+
|
|
49
|
+
/* Lightweight "server disconnected" banner. When the dev server is
|
|
50
|
+
* genuinely down (process restarting or crashed) the browser would
|
|
51
|
+
* otherwise show its own blank "site can't be reached" page — this keeps
|
|
52
|
+
* a branded, self-explanatory notice on screen while the client polls
|
|
53
|
+
* `/hmr-status` and reloads on recovery. Kept separate from the compile
|
|
54
|
+
* error overlay so it never clobbers a build-error message. The
|
|
55
|
+
* `data-hmr-overlay` attribute exempts it from HMR DOM diffing. */
|
|
56
|
+
const CONNECTION_LOST_BANNER_ID = 'absolutejs-connection-lost';
|
|
57
|
+
const showConnectionLostBanner = () => {
|
|
58
|
+
if (typeof document === 'undefined' || !document.body) return;
|
|
59
|
+
if (document.getElementById(CONNECTION_LOST_BANNER_ID)) return;
|
|
60
|
+
const banner = document.createElement('div');
|
|
61
|
+
banner.id = CONNECTION_LOST_BANNER_ID;
|
|
62
|
+
banner.setAttribute('data-hmr-overlay', 'true');
|
|
63
|
+
banner.style.cssText = [
|
|
64
|
+
'position:fixed',
|
|
65
|
+
'left:0',
|
|
66
|
+
'right:0',
|
|
67
|
+
'bottom:0',
|
|
68
|
+
'z-index:2147483646',
|
|
69
|
+
'padding:10px 16px',
|
|
70
|
+
'font:600 13px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace',
|
|
71
|
+
'color:#fff',
|
|
72
|
+
'background:#b91c1c',
|
|
73
|
+
'text-align:center',
|
|
74
|
+
'box-shadow:0 -2px 12px rgba(0,0,0,0.3)'
|
|
75
|
+
].join(';');
|
|
76
|
+
banner.textContent = 'AbsoluteJS · dev server disconnected — reconnecting…';
|
|
77
|
+
document.body.appendChild(banner);
|
|
78
|
+
};
|
|
79
|
+
const hideConnectionLostBanner = () => {
|
|
80
|
+
if (typeof document === 'undefined') return;
|
|
81
|
+
const banner = document.getElementById(CONNECTION_LOST_BANNER_ID);
|
|
82
|
+
if (banner && banner.parentNode) banner.parentNode.removeChild(banner);
|
|
83
|
+
};
|
|
84
|
+
|
|
35
85
|
// Initialize HMR globals
|
|
36
86
|
if (typeof window !== 'undefined') {
|
|
87
|
+
window.__ABS_HMR_TARGET__ = absoluteHmrClientTarget();
|
|
37
88
|
installAngularRemountGlobal();
|
|
38
89
|
if (!window.__HMR_MANIFEST__) {
|
|
39
90
|
window.__HMR_MANIFEST__ = {};
|
|
@@ -76,6 +127,7 @@ const hmrUpdateTypes = new Set([
|
|
|
76
127
|
'angular:component-update',
|
|
77
128
|
'angular:component-remount',
|
|
78
129
|
'angular:rebootstrap',
|
|
130
|
+
'angular-update',
|
|
79
131
|
'react-update',
|
|
80
132
|
'html-update',
|
|
81
133
|
'htmx-update',
|
|
@@ -91,6 +143,7 @@ type HMRMessage = {
|
|
|
91
143
|
affectedFrameworks?: string[];
|
|
92
144
|
column?: number;
|
|
93
145
|
error?: string;
|
|
146
|
+
fastRefreshSupported?: boolean;
|
|
94
147
|
file?: string;
|
|
95
148
|
framework?: string;
|
|
96
149
|
hasCSSChanges?: boolean;
|
|
@@ -106,9 +159,23 @@ type HMRMessage = {
|
|
|
106
159
|
serverDuration?: number;
|
|
107
160
|
serverVersions?: Record<string, number>;
|
|
108
161
|
};
|
|
162
|
+
timestamp?: number;
|
|
109
163
|
type: string;
|
|
110
164
|
};
|
|
111
165
|
|
|
166
|
+
const handleStylesheetUpdate = (message: HMRMessage) => {
|
|
167
|
+
const clientStart = performance.now();
|
|
168
|
+
void reloadCSSStylesheets(message.data.manifest ?? {}).then((applied) => {
|
|
169
|
+
sendAbsoluteHmrTiming({
|
|
170
|
+
clientStart,
|
|
171
|
+
kind: 'css',
|
|
172
|
+
outcome: applied ? 'applied' : 'failed',
|
|
173
|
+
serverMs: message.data.serverDuration,
|
|
174
|
+
updateId: message.timestamp
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
|
|
112
179
|
const handleHMRMessage = (message: HMRMessage) => {
|
|
113
180
|
if (hmrUpdateTypes.has(message.type)) {
|
|
114
181
|
hmrState.isHMRUpdating = true;
|
|
@@ -162,15 +229,15 @@ const handleHMRMessage = (message: HMRMessage) => {
|
|
|
162
229
|
// `__ng_hmr_load` blocks (see hmrInjectionPlugin.ts)
|
|
163
230
|
// listen here and re-fetch the applyMetadata module.
|
|
164
231
|
hideErrorOverlay();
|
|
165
|
-
const data = message
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
232
|
+
const { data } = message;
|
|
233
|
+
if (isRecord(data)) {
|
|
234
|
+
const id = Reflect.get(data, 'id');
|
|
235
|
+
if (typeof id !== 'string') break;
|
|
169
236
|
dispatchAngularComponentUpdate({
|
|
170
|
-
id
|
|
237
|
+
id,
|
|
171
238
|
timestamp:
|
|
172
|
-
typeof
|
|
173
|
-
?
|
|
239
|
+
typeof message.timestamp === 'number'
|
|
240
|
+
? message.timestamp
|
|
174
241
|
: Date.now()
|
|
175
242
|
});
|
|
176
243
|
}
|
|
@@ -185,15 +252,15 @@ const handleHMRMessage = (message: HMRMessage) => {
|
|
|
185
252
|
// `__absAngularRemount` global wired in
|
|
186
253
|
// `installAngularRemountGlobal`.
|
|
187
254
|
hideErrorOverlay();
|
|
188
|
-
const data = message
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
255
|
+
const { data } = message;
|
|
256
|
+
if (isRecord(data)) {
|
|
257
|
+
const id = Reflect.get(data, 'id');
|
|
258
|
+
if (typeof id !== 'string') break;
|
|
192
259
|
dispatchAngularComponentRemount({
|
|
193
|
-
id
|
|
260
|
+
id,
|
|
194
261
|
timestamp:
|
|
195
|
-
typeof
|
|
196
|
-
?
|
|
262
|
+
typeof message.timestamp === 'number'
|
|
263
|
+
? message.timestamp
|
|
197
264
|
: Date.now()
|
|
198
265
|
});
|
|
199
266
|
}
|
|
@@ -209,17 +276,17 @@ const handleHMRMessage = (message: HMRMessage) => {
|
|
|
209
276
|
// to dynamic-import the fresh bundle URL — re-importing
|
|
210
277
|
// re-runs the destroy + bootstrapApplication block.
|
|
211
278
|
hideErrorOverlay();
|
|
212
|
-
const data = message
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
window.__HMR_MANIFEST__ = data.manifest;
|
|
279
|
+
const { data } = message;
|
|
280
|
+
if (isRecord(data) && isStringRecord(data.manifest)) {
|
|
281
|
+
const { manifest } = data;
|
|
282
|
+
window.__HMR_MANIFEST__ = manifest;
|
|
217
283
|
}
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
284
|
+
const rebootstrap = Reflect.get(
|
|
285
|
+
window,
|
|
286
|
+
'__ABS_ANGULAR_REBOOTSTRAP__'
|
|
287
|
+
);
|
|
288
|
+
if (typeof rebootstrap === 'function') {
|
|
289
|
+
Promise.resolve(rebootstrap()).catch((err) => {
|
|
223
290
|
console.error(
|
|
224
291
|
'[absolutejs] angular:rebootstrap failed',
|
|
225
292
|
err
|
|
@@ -237,12 +304,17 @@ const handleHMRMessage = (message: HMRMessage) => {
|
|
|
237
304
|
handleRebuildError(message);
|
|
238
305
|
break;
|
|
239
306
|
case 'full-reload':
|
|
240
|
-
handleFullReload();
|
|
307
|
+
handleFullReload(message);
|
|
241
308
|
break;
|
|
242
309
|
case 'pong':
|
|
243
310
|
break;
|
|
244
311
|
case 'style-update':
|
|
245
|
-
|
|
312
|
+
handleStylesheetUpdate(message);
|
|
313
|
+
break;
|
|
314
|
+
case 'angular-update':
|
|
315
|
+
if (detectCurrentFramework() === 'angular') {
|
|
316
|
+
handleStylesheetUpdate(message);
|
|
317
|
+
}
|
|
246
318
|
break;
|
|
247
319
|
default:
|
|
248
320
|
break;
|
|
@@ -263,12 +335,14 @@ if (!(window.__HMR_WS__ && window.__HMR_WS__.readyState === WebSocket.OPEN)) {
|
|
|
263
335
|
|
|
264
336
|
wsc.onopen = function () {
|
|
265
337
|
hmrState.isConnected = true;
|
|
338
|
+
hideConnectionLostBanner();
|
|
266
339
|
sessionStorage.setItem('__HMR_CONNECTED__', 'true');
|
|
267
340
|
|
|
268
341
|
const currentFramework = detectCurrentFramework();
|
|
269
342
|
wsc.send(
|
|
270
343
|
JSON.stringify({
|
|
271
344
|
framework: currentFramework,
|
|
345
|
+
target: absoluteHmrClientTarget(),
|
|
272
346
|
type: 'ready'
|
|
273
347
|
})
|
|
274
348
|
);
|
|
@@ -305,6 +379,7 @@ if (!(window.__HMR_WS__ && window.__HMR_WS__.readyState === WebSocket.OPEN)) {
|
|
|
305
379
|
}
|
|
306
380
|
|
|
307
381
|
if (event.code !== WEBSOCKET_NORMAL_CLOSURE) {
|
|
382
|
+
showConnectionLostBanner();
|
|
308
383
|
let attempts = 0;
|
|
309
384
|
hmrState.reconnectTimeout = setTimeout(function pollServer() {
|
|
310
385
|
attempts++;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import type {} from '../../types/globals';
|
|
2
|
+
import type {
|
|
3
|
+
HMRApplyKind,
|
|
4
|
+
HMRApplyOutcome,
|
|
5
|
+
HMRClientTarget
|
|
6
|
+
} from '../../../types/messages';
|
|
7
|
+
|
|
8
|
+
const MAX_RETAINED_HMR_APPLIES = 50;
|
|
9
|
+
const HMR_APPLY_STORAGE_KEY = '__absolute_hmr_last_apply__';
|
|
10
|
+
|
|
11
|
+
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
12
|
+
typeof value === 'object' && value !== null;
|
|
13
|
+
|
|
14
|
+
const isHmrTarget = (value: unknown): value is HMRClientTarget =>
|
|
15
|
+
value === 'capacitor-android' ||
|
|
16
|
+
value === 'capacitor-ios' ||
|
|
17
|
+
value === 'capacitor-native' ||
|
|
18
|
+
value === 'web';
|
|
19
|
+
|
|
20
|
+
const isHmrKind = (value: unknown): value is HMRApplyKind =>
|
|
21
|
+
value === 'component' ||
|
|
22
|
+
value === 'css' ||
|
|
23
|
+
value === 'full-reload' ||
|
|
24
|
+
value === 'html' ||
|
|
25
|
+
value === 'htmx' ||
|
|
26
|
+
value === 'script';
|
|
27
|
+
|
|
28
|
+
const isHmrOutcome = (value: unknown): value is HMRApplyOutcome =>
|
|
29
|
+
value === 'applied' || value === 'failed' || value === 'reloaded';
|
|
30
|
+
|
|
31
|
+
type HmrApply = NonNullable<Window['__ABS_HMR_LAST_APPLY__']>;
|
|
32
|
+
|
|
33
|
+
const isHmrApply = (value: unknown): value is HmrApply =>
|
|
34
|
+
isRecord(value) &&
|
|
35
|
+
typeof value.clientMs === 'number' &&
|
|
36
|
+
typeof value.duration === 'number' &&
|
|
37
|
+
(value.kind === undefined || isHmrKind(value.kind)) &&
|
|
38
|
+
isHmrOutcome(value.outcome) &&
|
|
39
|
+
typeof value.serverMs === 'number' &&
|
|
40
|
+
isHmrTarget(value.target) &&
|
|
41
|
+
(value.updateId === undefined || typeof value.updateId === 'number');
|
|
42
|
+
|
|
43
|
+
const getSessionStorage = () => {
|
|
44
|
+
const storage = Reflect.get(window, 'sessionStorage');
|
|
45
|
+
if (!isRecord(storage)) return undefined;
|
|
46
|
+
|
|
47
|
+
return storage;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const persistHmrApply = (timing: HmrApply) => {
|
|
51
|
+
try {
|
|
52
|
+
const storage = getSessionStorage();
|
|
53
|
+
const setItem = storage && Reflect.get(storage, 'setItem');
|
|
54
|
+
if (typeof setItem !== 'function') return;
|
|
55
|
+
Reflect.apply(setItem, storage, [
|
|
56
|
+
HMR_APPLY_STORAGE_KEY,
|
|
57
|
+
JSON.stringify(timing)
|
|
58
|
+
]);
|
|
59
|
+
} catch {
|
|
60
|
+
// Storage may be unavailable in sandboxed or privacy-restricted documents.
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const absoluteHmrClientTarget = () => {
|
|
65
|
+
const currentLocation = Reflect.get(globalThis, 'location');
|
|
66
|
+
if (typeof currentLocation === 'object' && currentLocation !== null) {
|
|
67
|
+
const search = Reflect.get(currentLocation, 'search');
|
|
68
|
+
if (typeof search === 'string') {
|
|
69
|
+
const marker = new URLSearchParams(search).get('__absolute_target');
|
|
70
|
+
if (marker === 'capacitor-android') return marker;
|
|
71
|
+
if (marker === 'capacitor-ios') return marker;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const capacitor = Reflect.get(globalThis, 'Capacitor');
|
|
75
|
+
if (!isRecord(capacitor)) return 'web';
|
|
76
|
+
const getPlatform = Reflect.get(capacitor, 'getPlatform');
|
|
77
|
+
const isNativePlatform = Reflect.get(capacitor, 'isNativePlatform');
|
|
78
|
+
const platform =
|
|
79
|
+
typeof getPlatform === 'function'
|
|
80
|
+
? Reflect.apply(getPlatform, capacitor, [])
|
|
81
|
+
: undefined;
|
|
82
|
+
if (platform === 'android') return 'capacitor-android';
|
|
83
|
+
if (platform === 'ios') return 'capacitor-ios';
|
|
84
|
+
if (
|
|
85
|
+
typeof isNativePlatform === 'function' &&
|
|
86
|
+
Reflect.apply(isNativePlatform, capacitor, []) === true
|
|
87
|
+
) {
|
|
88
|
+
return 'capacitor-native';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return 'web';
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export const restoreAbsoluteHmrApply = () => {
|
|
95
|
+
try {
|
|
96
|
+
const storage = getSessionStorage();
|
|
97
|
+
const getItem = storage && Reflect.get(storage, 'getItem');
|
|
98
|
+
if (typeof getItem !== 'function') return;
|
|
99
|
+
const serialized = Reflect.apply(getItem, storage, [
|
|
100
|
+
HMR_APPLY_STORAGE_KEY
|
|
101
|
+
]);
|
|
102
|
+
if (typeof serialized !== 'string') return;
|
|
103
|
+
const timing: unknown = JSON.parse(serialized);
|
|
104
|
+
if (!isHmrApply(timing)) return;
|
|
105
|
+
window.__ABS_HMR_LAST_APPLY__ = timing;
|
|
106
|
+
window.__ABS_HMR_APPLIES__ = [timing];
|
|
107
|
+
} catch {
|
|
108
|
+
// A malformed or inaccessible entry should never affect HMR startup.
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
type SendHmrTimingOptions = {
|
|
113
|
+
clientStart: number;
|
|
114
|
+
kind?: HMRApplyKind;
|
|
115
|
+
outcome?: HMRApplyOutcome;
|
|
116
|
+
serverMs?: number;
|
|
117
|
+
updateId?: number;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export const sendAbsoluteHmrTiming = (options: SendHmrTimingOptions) => {
|
|
121
|
+
const clientMs = Math.round(performance.now() - options.clientStart);
|
|
122
|
+
const serverMs = options.serverMs ?? 0;
|
|
123
|
+
const timing = {
|
|
124
|
+
clientMs,
|
|
125
|
+
duration: serverMs + clientMs,
|
|
126
|
+
kind: options.kind,
|
|
127
|
+
outcome: options.outcome ?? 'applied',
|
|
128
|
+
serverMs,
|
|
129
|
+
target: absoluteHmrClientTarget(),
|
|
130
|
+
updateId: options.updateId
|
|
131
|
+
} satisfies NonNullable<Window['__ABS_HMR_LAST_APPLY__']>;
|
|
132
|
+
window.__ABS_HMR_LAST_APPLY__ = timing;
|
|
133
|
+
const applies = (window.__ABS_HMR_APPLIES__ ??= []);
|
|
134
|
+
applies.push(timing);
|
|
135
|
+
if (applies.length > MAX_RETAINED_HMR_APPLIES) {
|
|
136
|
+
applies.splice(0, applies.length - MAX_RETAINED_HMR_APPLIES);
|
|
137
|
+
}
|
|
138
|
+
persistHmrApply(timing);
|
|
139
|
+
if (!window.__HMR_WS__) return;
|
|
140
|
+
window.__HMR_WS__.send(JSON.stringify({ ...timing, type: 'hmr-timing' }));
|
|
141
|
+
};
|