nudge-ui 0.2.0
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/README.md +66 -0
- package/bin/nudge-ui.mjs +7 -0
- package/dist/LICENSE +21 -0
- package/dist/client.mjs +261 -0
- package/dist/compiler/ast.d.ts +18 -0
- package/dist/compiler/ast.js +75 -0
- package/dist/compiler/componentContractTypes.d.ts +19 -0
- package/dist/compiler/componentContractTypes.js +1 -0
- package/dist/compiler/componentContracts.d.ts +2 -0
- package/dist/compiler/componentContracts.js +260 -0
- package/dist/compiler/componentInstrumentation.d.ts +32 -0
- package/dist/compiler/componentInstrumentation.js +140 -0
- package/dist/compiler/componentPolicyResolution.d.ts +71 -0
- package/dist/compiler/componentPolicyResolution.js +388 -0
- package/dist/compiler/index.d.ts +9 -0
- package/dist/compiler/index.js +9 -0
- package/dist/compiler/packageComponentContracts.d.ts +32 -0
- package/dist/compiler/packageComponentContracts.js +308 -0
- package/dist/compiler/reactComponentProtocols.d.ts +145 -0
- package/dist/compiler/reactComponentProtocols.js +47 -0
- package/dist/compiler/reactIdentity.d.ts +15 -0
- package/dist/compiler/reactIdentity.js +339 -0
- package/dist/compiler/sourcePaths.d.ts +12 -0
- package/dist/compiler/sourcePaths.js +27 -0
- package/dist/css/dialects/index.d.ts +62 -0
- package/dist/css/dialects/index.js +103 -0
- package/dist/css/dialects/tailwind.d.ts +46 -0
- package/dist/css/dialects/tailwind.js +119 -0
- package/dist/css/dialects/vanillaExtract.d.ts +20 -0
- package/dist/css/dialects/vanillaExtract.js +32 -0
- package/dist/css/index.d.ts +10 -0
- package/dist/css/index.js +10 -0
- package/dist/css/model/index.d.ts +190 -0
- package/dist/css/model/index.js +10 -0
- package/dist/css/token-inventory/index.d.ts +26 -0
- package/dist/css/token-inventory/index.js +24 -0
- package/dist/css/token-inventory/inventory.d.ts +8 -0
- package/dist/css/token-inventory/inventory.js +421 -0
- package/dist/css/token-inventory/parseStylesheet.d.ts +16 -0
- package/dist/css/token-inventory/parseStylesheet.js +155 -0
- package/dist/css/token-inventory/policy.d.ts +47 -0
- package/dist/css/token-inventory/policy.js +50 -0
- package/dist/css/token-inventory/types.d.ts +97 -0
- package/dist/css/token-inventory/types.js +1 -0
- package/dist/css/value-semantics/borderSemantics.d.ts +28 -0
- package/dist/css/value-semantics/borderSemantics.js +91 -0
- package/dist/css/value-semantics/boxSemantics.d.ts +37 -0
- package/dist/css/value-semantics/boxSemantics.js +71 -0
- package/dist/css/value-semantics/colorSemantics.d.ts +99 -0
- package/dist/css/value-semantics/colorSemantics.js +526 -0
- package/dist/css/value-semantics/cssSyntax.d.ts +19 -0
- package/dist/css/value-semantics/cssSyntax.js +111 -0
- package/dist/css/value-semantics/fontSemantics.d.ts +35 -0
- package/dist/css/value-semantics/fontSemantics.js +131 -0
- package/dist/css/value-semantics/index.d.ts +20 -0
- package/dist/css/value-semantics/index.js +15 -0
- package/dist/css/value-semantics/propertyPolicy.d.ts +118 -0
- package/dist/css/value-semantics/propertyPolicy.js +356 -0
- package/dist/css/value-semantics/stringMaps.d.ts +2 -0
- package/dist/css/value-semantics/stringMaps.js +1 -0
- package/dist/css/value-semantics/structuredValues.d.ts +64 -0
- package/dist/css/value-semantics/structuredValues.js +250 -0
- package/dist/css/value-semantics/tokenInterpretation.d.ts +90 -0
- package/dist/css/value-semantics/tokenInterpretation.js +193 -0
- package/dist/css/virtual-design-tokens.d.ts +17 -0
- package/dist/hosts/astro/astroRuntimeConfig.d.ts +12 -0
- package/dist/hosts/astro/astroRuntimeConfig.js +26 -0
- package/dist/hosts/astro/clientAsset.d.ts +12 -0
- package/dist/hosts/astro/clientAsset.js +51 -0
- package/dist/hosts/astro/clientTransport.d.ts +3 -0
- package/dist/hosts/astro/clientTransport.js +57 -0
- package/dist/hosts/astro/index.d.ts +3 -0
- package/dist/hosts/astro/index.js +2 -0
- package/dist/hosts/astro/integration.d.ts +35 -0
- package/dist/hosts/astro/integration.js +96 -0
- package/dist/hosts/astro/middleware.d.ts +13 -0
- package/dist/hosts/astro/middleware.js +22 -0
- package/dist/hosts/astro/projectContext.d.ts +11 -0
- package/dist/hosts/astro/projectContext.js +34 -0
- package/dist/hosts/astro/responseInstrumentation.d.ts +41 -0
- package/dist/hosts/astro/responseInstrumentation.js +80 -0
- package/dist/hosts/next/index.d.ts +4 -0
- package/dist/hosts/next/index.js +7 -0
- package/dist/hosts/next/loader.d.ts +66 -0
- package/dist/hosts/next/loader.js +346 -0
- package/dist/hosts/next/loaders/identity-loader.cjs +228257 -0
- package/dist/hosts/next/loaders/loader-plugin.cjs +228257 -0
- package/dist/hosts/next/manifest.d.ts +38 -0
- package/dist/hosts/next/manifest.js +30 -0
- package/dist/hosts/next/mount.d.ts +12 -0
- package/dist/hosts/next/mount.js +23 -0
- package/dist/hosts/next/repositoryScope.d.ts +20 -0
- package/dist/hosts/next/repositoryScope.js +33 -0
- package/dist/hosts/next/sidecar.d.ts +27 -0
- package/dist/hosts/next/sidecar.js +526 -0
- package/dist/hosts/next/wrapper.d.ts +67 -0
- package/dist/hosts/next/wrapper.js +310 -0
- package/dist/hosts/static/cli.d.ts +12 -0
- package/dist/hosts/static/cli.js +77 -0
- package/dist/hosts/static/html/bootstrap.d.ts +27 -0
- package/dist/hosts/static/html/bootstrap.js +93 -0
- package/dist/hosts/static/index.d.ts +4 -0
- package/dist/hosts/static/index.js +4 -0
- package/dist/hosts/static/manifest.d.ts +18 -0
- package/dist/hosts/static/manifest.js +51 -0
- package/dist/hosts/static/server.d.ts +72 -0
- package/dist/hosts/static/server.js +554 -0
- package/dist/hosts/vite/index.d.ts +20 -0
- package/dist/hosts/vite/index.js +48 -0
- package/dist/hosts/vite/react.d.ts +67 -0
- package/dist/hosts/vite/react.js +231 -0
- package/dist/hosts/vite/tokens/activeStylesheets.d.ts +28 -0
- package/dist/hosts/vite/tokens/activeStylesheets.js +70 -0
- package/dist/hosts/vite/tokens/fileMap.d.ts +2 -0
- package/dist/hosts/vite/tokens/fileMap.js +1 -0
- package/dist/hosts/vite/tokens/viteStylesheetArtifacts.d.ts +46 -0
- package/dist/hosts/vite/tokens/viteStylesheetArtifacts.js +104 -0
- package/dist/hosts/vite/virtual/design-tokens.d.ts +9 -0
- package/dist/hosts/vite/virtual/design-tokens.js +7 -0
- package/dist/hosts/vite/virtual-design-tokens.d.ts +1 -0
- package/dist/hosts/vite/vite.d.ts +62 -0
- package/dist/hosts/vite/vite.js +854 -0
- package/dist/html/dom.d.ts +13 -0
- package/dist/html/dom.js +46 -0
- package/dist/html/identity.d.ts +40 -0
- package/dist/html/identity.js +196 -0
- package/dist/html/insertions.d.ts +26 -0
- package/dist/html/insertions.js +59 -0
- package/dist/inspector/agent/McpConnectionDialog.d.ts +26 -0
- package/dist/inspector/agent/McpConnectionDialog.js +135 -0
- package/dist/inspector/agent/client.d.ts +98 -0
- package/dist/inspector/agent/client.js +728 -0
- package/dist/inspector/agent/connectionStatus.d.ts +13 -0
- package/dist/inspector/agent/connectionStatus.js +35 -0
- package/dist/inspector/agent/httpTransport.d.ts +21 -0
- package/dist/inspector/agent/httpTransport.js +347 -0
- package/dist/inspector/agent/protocol.d.ts +95 -0
- package/dist/inspector/agent/protocol.js +9 -0
- package/dist/inspector/agent/verification.d.ts +39 -0
- package/dist/inspector/agent/verification.js +207 -0
- package/dist/inspector/canvas/CanvasCard.d.ts +10 -0
- package/dist/inspector/canvas/CanvasCard.js +275 -0
- package/dist/inspector/canvas/CanvasElementOverlay.d.ts +2 -0
- package/dist/inspector/canvas/CanvasElementOverlay.js +301 -0
- package/dist/inspector/canvas/CanvasWorkspace.d.ts +2 -0
- package/dist/inspector/canvas/CanvasWorkspace.js +301 -0
- package/dist/inspector/canvas/LockedWorkspaceNotice.d.ts +6 -0
- package/dist/inspector/canvas/LockedWorkspaceNotice.js +17 -0
- package/dist/inspector/canvas/StaleChangeIndicator.d.ts +7 -0
- package/dist/inspector/canvas/StaleChangeIndicator.js +43 -0
- package/dist/inspector/canvas/agentPresentation.d.ts +87 -0
- package/dist/inspector/canvas/agentPresentation.js +421 -0
- package/dist/inspector/canvas/canvasGestures.d.ts +12 -0
- package/dist/inspector/canvas/canvasGestures.js +21 -0
- package/dist/inspector/canvas/canvasStore.d.ts +108 -0
- package/dist/inspector/canvas/canvasStore.js +448 -0
- package/dist/inspector/canvas/frameProtocol.d.ts +231 -0
- package/dist/inspector/canvas/frameProtocol.js +165 -0
- package/dist/inspector/canvas/linkEligibility.d.ts +8 -0
- package/dist/inspector/canvas/linkEligibility.js +68 -0
- package/dist/inspector/canvas/measurementProjection.d.ts +8 -0
- package/dist/inspector/canvas/measurementProjection.js +16 -0
- package/dist/inspector/canvas/normalizeUrl.d.ts +7 -0
- package/dist/inspector/canvas/normalizeUrl.js +27 -0
- package/dist/inspector/canvas/projection.d.ts +41 -0
- package/dist/inspector/canvas/projection.js +232 -0
- package/dist/inspector/canvas/rendererBootstrap.d.ts +4 -0
- package/dist/inspector/canvas/rendererBootstrap.js +410 -0
- package/dist/inspector/canvas/rendererCidIndex.d.ts +11 -0
- package/dist/inspector/canvas/rendererCidIndex.js +21 -0
- package/dist/inspector/canvas/rendererElementSelector.d.ts +2 -0
- package/dist/inspector/canvas/rendererElementSelector.js +378 -0
- package/dist/inspector/canvas/rendererSelectionProxy.d.ts +2 -0
- package/dist/inspector/canvas/rendererSelectionProxy.js +61 -0
- package/dist/inspector/canvas/rendererStylesheet.d.ts +16 -0
- package/dist/inspector/canvas/rendererStylesheet.js +221 -0
- package/dist/inspector/canvas/resizeHandleScale.d.ts +13 -0
- package/dist/inspector/canvas/resizeHandleScale.js +20 -0
- package/dist/inspector/canvas/roleDetection.d.ts +5 -0
- package/dist/inspector/canvas/roleDetection.js +21 -0
- package/dist/inspector/canvas/sessionStore.d.ts +71 -0
- package/dist/inspector/canvas/sessionStore.js +453 -0
- package/dist/inspector/canvas/staleChangeDetector.d.ts +11 -0
- package/dist/inspector/canvas/staleChangeDetector.js +217 -0
- package/dist/inspector/canvas/toolbarScale.d.ts +7 -0
- package/dist/inspector/canvas/toolbarScale.js +11 -0
- package/dist/inspector/canvas/workspaceLease.d.ts +26 -0
- package/dist/inspector/canvas/workspaceLease.js +214 -0
- package/dist/inspector/changes/changesLog.d.ts +46 -0
- package/dist/inspector/changes/changesLog.js +209 -0
- package/dist/inspector/changes/codecs.d.ts +98 -0
- package/dist/inspector/changes/codecs.js +389 -0
- package/dist/inspector/changes/editModel.d.ts +74 -0
- package/dist/inspector/changes/editModel.js +120 -0
- package/dist/inspector/changes/managedStyleProjection.d.ts +6 -0
- package/dist/inspector/changes/managedStyleProjection.js +109 -0
- package/dist/inspector/changes/model.d.ts +13 -0
- package/dist/inspector/changes/model.js +163 -0
- package/dist/inspector/changes/presentation.d.ts +14 -0
- package/dist/inspector/changes/presentation.js +81 -0
- package/dist/inspector/changes/previewDiagnostics.d.ts +39 -0
- package/dist/inspector/changes/previewDiagnostics.js +172 -0
- package/dist/inspector/changes/structuralTypes.d.ts +35 -0
- package/dist/inspector/changes/structuralTypes.js +1 -0
- package/dist/inspector/changes/types.d.ts +76 -0
- package/dist/inspector/changes/types.js +16 -0
- package/dist/inspector/changes/workspaceChanges.d.ts +43 -0
- package/dist/inspector/changes/workspaceChanges.js +239 -0
- package/dist/inspector/clientManifest.d.ts +24 -0
- package/dist/inspector/clientManifest.js +69 -0
- package/dist/inspector/componentSemantics/ComponentPropsSection.d.ts +5 -0
- package/dist/inspector/componentSemantics/ComponentPropsSection.js +44 -0
- package/dist/inspector/componentSemantics/adapterRegistry.d.ts +11 -0
- package/dist/inspector/componentSemantics/adapterRegistry.js +75 -0
- package/dist/inspector/componentSemantics/boundaries.d.ts +2 -0
- package/dist/inspector/componentSemantics/boundaries.js +10 -0
- package/dist/inspector/componentSemantics/changeAction.d.ts +3 -0
- package/dist/inspector/componentSemantics/changeAction.js +6 -0
- package/dist/inspector/componentSemantics/changeModel.d.ts +8 -0
- package/dist/inspector/componentSemantics/changeModel.js +60 -0
- package/dist/inspector/componentSemantics/index.d.ts +4 -0
- package/dist/inspector/componentSemantics/index.js +2 -0
- package/dist/inspector/componentSemantics/reactRuntime.d.ts +10 -0
- package/dist/inspector/componentSemantics/reactRuntime.js +186 -0
- package/dist/inspector/componentSemantics/runtimeBridge.d.ts +25 -0
- package/dist/inspector/componentSemantics/runtimeBridge.js +161 -0
- package/dist/inspector/componentSemantics/runtimeTypes.d.ts +2 -0
- package/dist/inspector/componentSemantics/runtimeTypes.js +1 -0
- package/dist/inspector/componentSemantics/textBinding.d.ts +69 -0
- package/dist/inspector/componentSemantics/textBinding.js +514 -0
- package/dist/inspector/componentSemantics/types.d.ts +96 -0
- package/dist/inspector/componentSemantics/types.js +5 -0
- package/dist/inspector/conformance/borderCases.d.ts +7 -0
- package/dist/inspector/conformance/borderCases.js +428 -0
- package/dist/inspector/conformance/colorCases.d.ts +8 -0
- package/dist/inspector/conformance/colorCases.js +470 -0
- package/dist/inspector/conformance/fixture.d.ts +68 -0
- package/dist/inspector/conformance/fixture.js +153 -0
- package/dist/inspector/conformance/projection.d.ts +2 -0
- package/dist/inspector/conformance/projection.js +3 -0
- package/dist/inspector/conformance/spacingCases.d.ts +6 -0
- package/dist/inspector/conformance/spacingCases.js +417 -0
- package/dist/inspector/conformance/typographyCases.d.ts +7 -0
- package/dist/inspector/conformance/typographyCases.js +174 -0
- package/dist/inspector/editScope.d.ts +4 -0
- package/dist/inspector/editScope.js +5 -0
- package/dist/inspector/index.d.ts +20 -0
- package/dist/inspector/index.js +236 -0
- package/dist/inspector/inline-text/inlineTextEditor.d.ts +74 -0
- package/dist/inspector/inline-text/inlineTextEditor.js +1207 -0
- package/dist/inspector/inline-text/inlineTextLifecycle.d.ts +2 -0
- package/dist/inspector/inline-text/inlineTextLifecycle.js +17 -0
- package/dist/inspector/inline-text/textChangeBoundary.d.ts +6 -0
- package/dist/inspector/inline-text/textChangeBoundary.js +1 -0
- package/dist/inspector/inspection/bridge.d.ts +72 -0
- package/dist/inspector/inspection/bridge.js +134 -0
- package/dist/inspector/inspection/browserCssInspection.d.ts +74 -0
- package/dist/inspector/inspection/browserCssInspection.js +317 -0
- package/dist/inspector/inspection/browserCssInspectionRegistry.d.ts +12 -0
- package/dist/inspector/inspection/browserCssInspectionRegistry.js +66 -0
- package/dist/inspector/inspection/selectionProperty.d.ts +32 -0
- package/dist/inspector/inspection/selectionProperty.js +33 -0
- package/dist/inspector/inspection/useBrowserCssInspection.d.ts +20 -0
- package/dist/inspector/inspection/useBrowserCssInspection.js +159 -0
- package/dist/inspector/overlay/DropGuideOverlay.d.ts +17 -0
- package/dist/inspector/overlay/DropGuideOverlay.js +17 -0
- package/dist/inspector/overlay/InspectorOverlay.d.ts +5 -0
- package/dist/inspector/overlay/InspectorOverlay.js +328 -0
- package/dist/inspector/overlay/MeasurementGuideOverlay.d.ts +19 -0
- package/dist/inspector/overlay/MeasurementGuideOverlay.js +40 -0
- package/dist/inspector/overlay/clickPolicy.d.ts +7 -0
- package/dist/inspector/overlay/clickPolicy.js +13 -0
- package/dist/inspector/overlay/dropGuide.d.ts +22 -0
- package/dist/inspector/overlay/dropGuide.js +48 -0
- package/dist/inspector/overlay/elementSelector.d.ts +1 -0
- package/dist/inspector/overlay/elementSelector.js +100 -0
- package/dist/inspector/overlay/frameThrottle.d.ts +10 -0
- package/dist/inspector/overlay/frameThrottle.js +38 -0
- package/dist/inspector/overlay/interactionStyles.d.ts +3 -0
- package/dist/inspector/overlay/interactionStyles.js +70 -0
- package/dist/inspector/overlay/measurementGeometry.d.ts +25 -0
- package/dist/inspector/overlay/measurementGeometry.js +104 -0
- package/dist/inspector/overlay/overlayGeometry.d.ts +40 -0
- package/dist/inspector/overlay/overlayGeometry.js +59 -0
- package/dist/inspector/overlay/selectedGeometry.d.ts +7 -0
- package/dist/inspector/overlay/selectedGeometry.js +51 -0
- package/dist/inspector/overlay/structuralGestures.d.ts +28 -0
- package/dist/inspector/overlay/structuralGestures.js +180 -0
- package/dist/inspector/projection/cssEscapes.d.ts +3 -0
- package/dist/inspector/projection/cssEscapes.js +20 -0
- package/dist/inspector/projection/managedStylesheet.d.ts +33 -0
- package/dist/inspector/projection/managedStylesheet.js +240 -0
- package/dist/inspector/projection/renderedInstance.d.ts +56 -0
- package/dist/inspector/projection/renderedInstance.js +306 -0
- package/dist/inspector/projection/structuralProjection.d.ts +93 -0
- package/dist/inspector/projection/structuralProjection.js +560 -0
- package/dist/inspector/projection/structuralProjectionBoundary.d.ts +5 -0
- package/dist/inspector/projection/structuralProjectionBoundary.js +65 -0
- package/dist/inspector/projection/textProjection.d.ts +53 -0
- package/dist/inspector/projection/textProjection.js +705 -0
- package/dist/inspector/projection/workspaceProjection.d.ts +43 -0
- package/dist/inspector/projection/workspaceProjection.js +58 -0
- package/dist/inspector/prompt/PromptSettingsDialog.d.ts +15 -0
- package/dist/inspector/prompt/PromptSettingsDialog.js +17 -0
- package/dist/inspector/prompt/clipboardHandoff.d.ts +34 -0
- package/dist/inspector/prompt/clipboardHandoff.js +212 -0
- package/dist/inspector/prompt/copyToClipboard.d.ts +1 -0
- package/dist/inspector/prompt/copyToClipboard.js +34 -0
- package/dist/inspector/prompt/detectFramework.d.ts +6 -0
- package/dist/inspector/prompt/detectFramework.js +4 -0
- package/dist/inspector/prompt/generatePrompt.d.ts +7 -0
- package/dist/inspector/prompt/generatePrompt.js +391 -0
- package/dist/inspector/prompt/promptSettings.d.ts +8 -0
- package/dist/inspector/prompt/promptSettings.js +28 -0
- package/dist/inspector/runtime/devFlag.d.ts +28 -0
- package/dist/inspector/runtime/devFlag.js +50 -0
- package/dist/inspector/runtime/documentStylesheetOrder.d.ts +19 -0
- package/dist/inspector/runtime/documentStylesheetOrder.js +89 -0
- package/dist/inspector/runtime/domRealm.d.ts +4 -0
- package/dist/inspector/runtime/domRealm.js +11 -0
- package/dist/inspector/runtime/runtimeConfig.d.ts +119 -0
- package/dist/inspector/runtime/runtimeConfig.js +276 -0
- package/dist/inspector/runtime/staticHtmlRuntimeIdentity.d.ts +32 -0
- package/dist/inspector/runtime/staticHtmlRuntimeIdentity.js +149 -0
- package/dist/inspector/runtime/useRuntimeConfig.d.ts +10 -0
- package/dist/inspector/runtime/useRuntimeConfig.js +13 -0
- package/dist/inspector/selection/editScope.d.ts +32 -0
- package/dist/inspector/selection/editScope.js +140 -0
- package/dist/inspector/selection/editTarget.d.ts +8 -0
- package/dist/inspector/selection/editTarget.js +11 -0
- package/dist/inspector/selection/hierarchy.d.ts +7 -0
- package/dist/inspector/selection/hierarchy.js +42 -0
- package/dist/inspector/selection/resolveSelection.d.ts +10 -0
- package/dist/inspector/selection/resolveSelection.js +60 -0
- package/dist/inspector/selection/selectionStore.d.ts +41 -0
- package/dist/inspector/selection/selectionStore.js +262 -0
- package/dist/inspector/selection/selectionTarget.d.ts +5 -0
- package/dist/inspector/selection/selectionTarget.js +50 -0
- package/dist/inspector/selection/sourceSite.d.ts +2 -0
- package/dist/inspector/selection/sourceSite.js +12 -0
- package/dist/inspector/selection/styleSelection.d.ts +22 -0
- package/dist/inspector/selection/styleSelection.js +104 -0
- package/dist/inspector/session/index.d.ts +3 -0
- package/dist/inspector/session/index.js +2 -0
- package/dist/inspector/session/lifecycle.d.ts +22 -0
- package/dist/inspector/session/lifecycle.js +63 -0
- package/dist/inspector/session/sessionContext.d.ts +21 -0
- package/dist/inspector/session/sessionContext.js +28 -0
- package/dist/inspector/session/sessionFactory.d.ts +29 -0
- package/dist/inspector/session/sessionFactory.js +73 -0
- package/dist/inspector/settings/SettingsDialog.d.ts +12 -0
- package/dist/inspector/settings/SettingsDialog.js +46 -0
- package/dist/inspector/shell/AppShell.d.ts +2 -0
- package/dist/inspector/shell/AppShell.js +9 -0
- package/dist/inspector/shell/ChangesLog.d.ts +6 -0
- package/dist/inspector/shell/ChangesLog.js +92 -0
- package/dist/inspector/shell/CopyPromptButton.d.ts +9 -0
- package/dist/inspector/shell/CopyPromptButton.js +159 -0
- package/dist/inspector/shell/DomNavigation.d.ts +8 -0
- package/dist/inspector/shell/DomNavigation.js +30 -0
- package/dist/inspector/shell/EmptyState.d.ts +2 -0
- package/dist/inspector/shell/EmptyState.js +15 -0
- package/dist/inspector/shell/InspectorShell.d.ts +11 -0
- package/dist/inspector/shell/InspectorShell.js +268 -0
- package/dist/inspector/shell/openStore.d.ts +6 -0
- package/dist/inspector/shell/openStore.js +29 -0
- package/dist/inspector/shell/panelLayout.d.ts +2 -0
- package/dist/inspector/shell/panelLayout.js +29 -0
- package/dist/inspector/shell/shortcuts.d.ts +3 -0
- package/dist/inspector/shell/shortcuts.js +25 -0
- package/dist/inspector/shell/stateValue.d.ts +3 -0
- package/dist/inspector/shell/stateValue.js +34 -0
- package/dist/inspector/shell/styleState.d.ts +7 -0
- package/dist/inspector/shell/styleState.js +13 -0
- package/dist/inspector/spacing/projection.d.ts +43 -0
- package/dist/inspector/spacing/projection.js +136 -0
- package/dist/inspector/styleEditors/AppearanceSection.d.ts +13 -0
- package/dist/inspector/styleEditors/AppearanceSection.js +6 -0
- package/dist/inspector/styleEditors/AspectRatioField.d.ts +17 -0
- package/dist/inspector/styleEditors/AspectRatioField.js +10 -0
- package/dist/inspector/styleEditors/BorderEditor.d.ts +13 -0
- package/dist/inspector/styleEditors/BorderEditor.js +295 -0
- package/dist/inspector/styleEditors/BorderRadiusEditor.d.ts +14 -0
- package/dist/inspector/styleEditors/BorderRadiusEditor.js +108 -0
- package/dist/inspector/styleEditors/BoxShadowEditor.d.ts +13 -0
- package/dist/inspector/styleEditors/BoxShadowEditor.js +13 -0
- package/dist/inspector/styleEditors/ColorPicker.d.ts +15 -0
- package/dist/inspector/styleEditors/ColorPicker.js +73 -0
- package/dist/inspector/styleEditors/GapField.d.ts +17 -0
- package/dist/inspector/styleEditors/GapField.js +12 -0
- package/dist/inspector/styleEditors/GridChildSection.d.ts +14 -0
- package/dist/inspector/styleEditors/GridChildSection.js +91 -0
- package/dist/inspector/styleEditors/GridPicker.d.ts +13 -0
- package/dist/inspector/styleEditors/GridPicker.js +179 -0
- package/dist/inspector/styleEditors/GridSection.d.ts +17 -0
- package/dist/inspector/styleEditors/GridSection.js +27 -0
- package/dist/inspector/styleEditors/GridValueField.d.ts +17 -0
- package/dist/inspector/styleEditors/GridValueField.js +70 -0
- package/dist/inspector/styleEditors/InsetSection.d.ts +15 -0
- package/dist/inspector/styleEditors/InsetSection.js +15 -0
- package/dist/inspector/styleEditors/LayoutBlockedIndicator.d.ts +6 -0
- package/dist/inspector/styleEditors/LayoutBlockedIndicator.js +6 -0
- package/dist/inspector/styleEditors/LayoutComboField.d.ts +18 -0
- package/dist/inspector/styleEditors/LayoutComboField.js +138 -0
- package/dist/inspector/styleEditors/LayoutDropdown.d.ts +14 -0
- package/dist/inspector/styleEditors/LayoutDropdown.js +34 -0
- package/dist/inspector/styleEditors/LayoutSection.d.ts +13 -0
- package/dist/inspector/styleEditors/LayoutSection.js +342 -0
- package/dist/inspector/styleEditors/OpacityEditor.d.ts +13 -0
- package/dist/inspector/styleEditors/OpacityEditor.js +34 -0
- package/dist/inspector/styleEditors/PositionInsets.d.ts +15 -0
- package/dist/inspector/styleEditors/PositionInsets.js +12 -0
- package/dist/inspector/styleEditors/SpacingBox.d.ts +29 -0
- package/dist/inspector/styleEditors/SpacingBox.js +189 -0
- package/dist/inspector/styleEditors/Typography.d.ts +13 -0
- package/dist/inspector/styleEditors/Typography.js +137 -0
- package/dist/inspector/styleEditors/completeCssValue.d.ts +8 -0
- package/dist/inspector/styleEditors/completeCssValue.js +34 -0
- package/dist/inspector/styleEditors/gridChildModel.d.ts +74 -0
- package/dist/inspector/styleEditors/gridChildModel.js +138 -0
- package/dist/inspector/styleEditors/layoutValue.d.ts +24 -0
- package/dist/inspector/styleEditors/layoutValue.js +103 -0
- package/dist/inspector/styleEditors/nudgeValue.d.ts +8 -0
- package/dist/inspector/styleEditors/nudgeValue.js +71 -0
- package/dist/inspector/styleEditors/rowLookup.d.ts +11 -0
- package/dist/inspector/styleEditors/rowLookup.js +13 -0
- package/dist/inspector/styleEditors/stringRecord.d.ts +4 -0
- package/dist/inspector/styleEditors/stringRecord.js +1 -0
- package/dist/inspector/styleEditors/valuePolicy.d.ts +20 -0
- package/dist/inspector/styleEditors/valuePolicy.js +82 -0
- package/dist/inspector/testing.d.ts +10 -0
- package/dist/inspector/testing.js +9 -0
- package/dist/inspector/tokens/TokenChip.d.ts +24 -0
- package/dist/inspector/tokens/TokenChip.js +23 -0
- package/dist/inspector/tokens/TokenDropdown.d.ts +13 -0
- package/dist/inspector/tokens/TokenDropdown.js +59 -0
- package/dist/inspector/tokens/TokenField.d.ts +68 -0
- package/dist/inspector/tokens/TokenField.js +485 -0
- package/dist/inspector/tokens/TokenLabel.d.ts +7 -0
- package/dist/inspector/tokens/TokenLabel.js +23 -0
- package/dist/inspector/tokens/TokensPanel.d.ts +5 -0
- package/dist/inspector/tokens/TokensPanel.js +47 -0
- package/dist/inspector/tokens/catalog.d.ts +51 -0
- package/dist/inspector/tokens/catalog.js +184 -0
- package/dist/inspector/tokens/editActions.d.ts +35 -0
- package/dist/inspector/tokens/editActions.js +164 -0
- package/dist/inspector/tokens/resolution/cascade.d.ts +14 -0
- package/dist/inspector/tokens/resolution/cascade.js +31 -0
- package/dist/inspector/tokens/resolution/cssomCollector.d.ts +43 -0
- package/dist/inspector/tokens/resolution/cssomCollector.js +528 -0
- package/dist/inspector/tokens/resolution/selectorSemantics.d.ts +12 -0
- package/dist/inspector/tokens/resolution/selectorSemantics.js +106 -0
- package/dist/inspector/tokens/resolution.d.ts +56 -0
- package/dist/inspector/tokens/resolution.js +1401 -0
- package/dist/inspector/tokens/tokenEdits.d.ts +3 -0
- package/dist/inspector/tokens/tokenEdits.js +22 -0
- package/dist/inspector/tokens/valueSemanticsAdapter.d.ts +6 -0
- package/dist/inspector/tokens/valueSemanticsAdapter.js +68 -0
- package/dist/inspector/ui/AtRuleContext.d.ts +18 -0
- package/dist/inspector/ui/AtRuleContext.js +54 -0
- package/dist/inspector/ui/Button.d.ts +9 -0
- package/dist/inspector/ui/Button.js +4 -0
- package/dist/inspector/ui/ColorSwatch.d.ts +7 -0
- package/dist/inspector/ui/ColorSwatch.js +6 -0
- package/dist/inspector/ui/ControlSurface.d.ts +14 -0
- package/dist/inspector/ui/ControlSurface.js +10 -0
- package/dist/inspector/ui/FieldRow.d.ts +14 -0
- package/dist/inspector/ui/FieldRow.js +15 -0
- package/dist/inspector/ui/IconButton.d.ts +14 -0
- package/dist/inspector/ui/IconButton.js +5 -0
- package/dist/inspector/ui/InspectorPopover.d.ts +17 -0
- package/dist/inspector/ui/InspectorPopover.js +13 -0
- package/dist/inspector/ui/PopoverListbox.d.ts +37 -0
- package/dist/inspector/ui/PopoverListbox.js +21 -0
- package/dist/inspector/ui/SegmentedControl.d.ts +24 -0
- package/dist/inspector/ui/SegmentedControl.js +16 -0
- package/dist/inspector/ui/Select.d.ts +25 -0
- package/dist/inspector/ui/Select.js +56 -0
- package/dist/inspector/ui/SideValuesField.d.ts +44 -0
- package/dist/inspector/ui/SideValuesField.js +76 -0
- package/dist/inspector/ui/StatusCallout.d.ts +9 -0
- package/dist/inspector/ui/StatusCallout.js +4 -0
- package/dist/inspector/ui/TextInput.d.ts +12 -0
- package/dist/inspector/ui/TextInput.js +5 -0
- package/dist/inspector/ui/ToggleButton.d.ts +11 -0
- package/dist/inspector/ui/ToggleButton.js +6 -0
- package/dist/inspector/ui/assets/grid.svg +14 -0
- package/dist/inspector/ui/css.d.ts +9 -0
- package/dist/inspector/ui/labels.d.ts +1 -0
- package/dist/inspector/ui/labels.js +7 -0
- package/dist/inspector/ui/styles.d.ts +1 -0
- package/dist/inspector/ui/styles.js +68 -0
- package/dist/inspector/virtual-modules.d.ts +7 -0
- package/dist/inspector/vite-env.d.ts +10 -0
- package/dist/internal/agent-protocol.d.ts +232 -0
- package/dist/internal/agent-protocol.js +237 -0
- package/dist/nudge-ui.mjs +15722 -0
- package/dist/project/files.d.ts +19 -0
- package/dist/project/files.js +226 -0
- package/dist/project/identity.d.ts +6 -0
- package/dist/project/identity.js +19 -0
- package/dist/project/pathPolicy.d.ts +8 -0
- package/dist/project/pathPolicy.js +12 -0
- package/dist/project/tokens.d.ts +36 -0
- package/dist/project/tokens.js +223 -0
- package/dist/transport/index.d.ts +8 -0
- package/dist/transport/index.js +8 -0
- package/dist/transport/routes.d.ts +13 -0
- package/dist/transport/routes.js +16 -0
- package/package.json +137 -0
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
import { createServer } from "node:http";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { realpath } from "node:fs/promises";
|
|
5
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
6
|
+
import { buildManifest, } from "./manifest.js";
|
|
7
|
+
import { extractComponentContracts } from "../../compiler/componentContracts.js";
|
|
8
|
+
import { createProjectFileWatcher, } from "../../project/files.js";
|
|
9
|
+
import { createProjectTokenSnapshot } from "../../project/tokens.js";
|
|
10
|
+
import { NUDGE_UI_CLIENT_PATH, NUDGE_UI_MANIFEST_PATH, NUDGE_UI_RELOAD_PATH, NUDGE_UI_ROUTE_PREFIX, } from "../../transport/index.js";
|
|
11
|
+
/**
|
|
12
|
+
* Loopback-only manifest/reload sidecar (ADR-0010).
|
|
13
|
+
*
|
|
14
|
+
* One server per dev-server process, guarded against double-spawn because
|
|
15
|
+
* Next re-evaluates `next.config` more than once. Same-origin access without
|
|
16
|
+
* CORS comes from a `beforeFiles` rewrite proxying `/__nudge_ui__/*` to the
|
|
17
|
+
* sidecar port — both are wrapper-owned config, so the user touchpoint stays
|
|
18
|
+
* at one line.
|
|
19
|
+
*
|
|
20
|
+
* Routes:
|
|
21
|
+
* - GET /__nudge_ui__/client.mjs — the shared self-contained inspector client.
|
|
22
|
+
* - GET /__nudge_ui__/manifest — the frozen runtime snapshot, including
|
|
23
|
+
* the Stage 4 token lifecycle when `tokens` is enabled: scanned project CSS
|
|
24
|
+
* feeds a deterministic generation, and each settled watcher batch bumps
|
|
25
|
+
* the generation and emits exactly one reload notification.
|
|
26
|
+
* - GET /__nudge_ui__/reload — SSE revision notifications after settled
|
|
27
|
+
* file changes.
|
|
28
|
+
*/
|
|
29
|
+
const STATE_DIR_SEGMENT = ".next";
|
|
30
|
+
const packageRequire = createRequire(import.meta.url);
|
|
31
|
+
let inspectorClientPath;
|
|
32
|
+
const GLOBAL_KEY = Symbol.for("nudge-ui/next/sidecar");
|
|
33
|
+
/**
|
|
34
|
+
* One sidecar per process per configuration. The key keeps a token-enabled
|
|
35
|
+
* server from being conflated with a bare manifest-only server created
|
|
36
|
+
* elsewhere in the same process (tests, multiple projects).
|
|
37
|
+
*/
|
|
38
|
+
function globalState(key) {
|
|
39
|
+
// SAFETY: The GLOBAL_KEY symbol names the one global slot this module owns and writes itself.
|
|
40
|
+
const holder = globalThis;
|
|
41
|
+
if (!holder[GLOBAL_KEY])
|
|
42
|
+
holder[GLOBAL_KEY] = new Map();
|
|
43
|
+
let entry = holder[GLOBAL_KEY].get(key);
|
|
44
|
+
if (!entry) {
|
|
45
|
+
entry = {};
|
|
46
|
+
holder[GLOBAL_KEY].set(key, entry);
|
|
47
|
+
}
|
|
48
|
+
return entry;
|
|
49
|
+
}
|
|
50
|
+
function stateDirFor(root) {
|
|
51
|
+
return join(root, STATE_DIR_SEGMENT);
|
|
52
|
+
}
|
|
53
|
+
function portFilePath(root) {
|
|
54
|
+
return join(stateDirFor(root), "nudge-ui-sidecar.json");
|
|
55
|
+
}
|
|
56
|
+
const CONTRACT_SOURCE_EXT = /\.(tsx|jsx)$/;
|
|
57
|
+
const SCAN_EXCLUDED_SEGMENTS = new Set([".git", ".next", "build", "dist", "node_modules"]);
|
|
58
|
+
/** Upper bound on examined project source files; truncation is announced. */
|
|
59
|
+
const SCAN_MAX_SOURCES = 5000;
|
|
60
|
+
/** Returns whether a directory declares a package-manager workspace. */
|
|
61
|
+
function hasWorkspaceManifest(directory) {
|
|
62
|
+
if (existsSync(join(directory, "pnpm-workspace.yaml")))
|
|
63
|
+
return true;
|
|
64
|
+
try {
|
|
65
|
+
// SAFETY: The parsed JSON shape is validated by the Array.isArray guards below before use.
|
|
66
|
+
const packageJson = JSON.parse(readFileSync(join(directory, "package.json"), "utf8"));
|
|
67
|
+
if (Array.isArray(packageJson.workspaces))
|
|
68
|
+
return true;
|
|
69
|
+
if (typeof packageJson.workspaces !== "object" || packageJson.workspaces === null)
|
|
70
|
+
return false;
|
|
71
|
+
// SAFETY: The packages field is validated by Array.isArray before use.
|
|
72
|
+
const packages = packageJson.workspaces.packages;
|
|
73
|
+
return Array.isArray(packages);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** Upper bound on ancestors examined when searching for a workspace root. */
|
|
80
|
+
const MAX_WORKSPACE_SEARCH_DEPTH = 5;
|
|
81
|
+
/**
|
|
82
|
+
* Finds the nearest declared workspace root by walking upward from the app.
|
|
83
|
+
*
|
|
84
|
+
* A Next app normally runs with its app directory as `process.cwd()`. When a
|
|
85
|
+
* workspace manifest is present above that directory, the workspace is the
|
|
86
|
+
* smallest safe default that can include sibling authored stylesheets. The
|
|
87
|
+
* walk is bounded and never promotes the filesystem root itself, so a stray
|
|
88
|
+
* manifest at `/` cannot turn the whole machine into the token scan root.
|
|
89
|
+
* With no manifest found, scanning remains confined to the app root.
|
|
90
|
+
*/
|
|
91
|
+
function nearestWorkspaceRoot(root) {
|
|
92
|
+
let directory = root;
|
|
93
|
+
for (let depth = 0; depth <= MAX_WORKSPACE_SEARCH_DEPTH; depth += 1) {
|
|
94
|
+
if (hasWorkspaceManifest(directory)) {
|
|
95
|
+
if (dirname(directory) === directory)
|
|
96
|
+
return root;
|
|
97
|
+
return directory;
|
|
98
|
+
}
|
|
99
|
+
const parent = dirname(directory);
|
|
100
|
+
if (parent === directory)
|
|
101
|
+
return root;
|
|
102
|
+
directory = parent;
|
|
103
|
+
}
|
|
104
|
+
return root;
|
|
105
|
+
}
|
|
106
|
+
async function tokenScanRoots(root, sourceRoots = []) {
|
|
107
|
+
const workspaceRoot = nearestWorkspaceRoot(root);
|
|
108
|
+
const configuredRoots = sourceRoots.map((sourceRoot) => resolve(root, sourceRoot));
|
|
109
|
+
const canonicalRoots = await Promise.all([root, workspaceRoot, ...configuredRoots].map((scanRoot) => realpath(scanRoot).catch(() => scanRoot)));
|
|
110
|
+
return [...new Set(canonicalRoots)];
|
|
111
|
+
}
|
|
112
|
+
function isWithinRoot(root, candidate) {
|
|
113
|
+
const pathFromRoot = relative(root, candidate);
|
|
114
|
+
return pathFromRoot === ""
|
|
115
|
+
|| (!pathFromRoot.startsWith(`..${sep}`)
|
|
116
|
+
&& pathFromRoot !== ".."
|
|
117
|
+
&& !isAbsolute(pathFromRoot));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Extracts component contracts directly from project sources.
|
|
121
|
+
*
|
|
122
|
+
* Compile-time loader postings alone leave a restart gap: Turbopack's
|
|
123
|
+
* persistent cache serves previously compiled modules without re-running
|
|
124
|
+
* loaders, so a fresh sidecar would publish an empty contract catalog until
|
|
125
|
+
* every file happens to recompile. Reading the same authored sources the
|
|
126
|
+
* loader reads keeps the manifest coherent across dev-server restarts.
|
|
127
|
+
*
|
|
128
|
+
* `canonicalRoot` must be the realpath'd project root so aggregation keys
|
|
129
|
+
* match both loader postings and watcher events regardless of how the host
|
|
130
|
+
* spelled the working directory.
|
|
131
|
+
*/
|
|
132
|
+
async function scanProjectContracts(canonicalRoot, apply) {
|
|
133
|
+
const queue = [canonicalRoot];
|
|
134
|
+
const files = new Set();
|
|
135
|
+
let examined = 0;
|
|
136
|
+
let truncated = false;
|
|
137
|
+
while (queue.length > 0 && !truncated) {
|
|
138
|
+
const directory = queue.shift();
|
|
139
|
+
let entries;
|
|
140
|
+
try {
|
|
141
|
+
entries = readdirSync(directory, { withFileTypes: true });
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
// Deterministic order keeps any truncation boundary stable across runs.
|
|
147
|
+
entries.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
148
|
+
for (const entry of entries) {
|
|
149
|
+
const absolutePath = join(directory, entry.name);
|
|
150
|
+
if (entry.isDirectory()) {
|
|
151
|
+
if (!SCAN_EXCLUDED_SEGMENTS.has(entry.name))
|
|
152
|
+
queue.push(absolutePath);
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (!CONTRACT_SOURCE_EXT.test(entry.name))
|
|
156
|
+
continue;
|
|
157
|
+
if (++examined > SCAN_MAX_SOURCES) {
|
|
158
|
+
truncated = true;
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
const relativeFile = relative(canonicalRoot, absolutePath).split("\\").join("/");
|
|
162
|
+
files.add(relativeFile);
|
|
163
|
+
try {
|
|
164
|
+
const source = readFileSync(absolutePath, "utf8");
|
|
165
|
+
apply(relativeFile, extractComponentContracts(source, relativeFile));
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
/* unreadable sources contribute no knowledge */
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (truncated) {
|
|
173
|
+
console.warn(`[nudge-ui] component contract scan stopped at ${SCAN_MAX_SOURCES} sources; `
|
|
174
|
+
+ "contracts beyond that bound are missing until their files compile.");
|
|
175
|
+
}
|
|
176
|
+
return { truncated, files };
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Reads one source file only while its size is stable across the read.
|
|
180
|
+
* Editors that truncate-then-write can expose half a file at read time; a
|
|
181
|
+
* syntactically valid prefix would otherwise replace good contracts with
|
|
182
|
+
* wrong ones until the next settled batch.
|
|
183
|
+
*/
|
|
184
|
+
function readStableSource(absolutePath) {
|
|
185
|
+
try {
|
|
186
|
+
const sizeBefore = statSync(absolutePath).size;
|
|
187
|
+
const source = readFileSync(absolutePath, "utf8");
|
|
188
|
+
if (statSync(absolutePath).size !== sizeBefore || Buffer.byteLength(source) !== sizeBefore) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
return { source };
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/** Removes a stale port file left by a crashed previous run. */
|
|
198
|
+
export function clearStaleSidecarState(root) {
|
|
199
|
+
try {
|
|
200
|
+
// SAFETY: The JSON.parse result is validated by the typeof guard below before use.
|
|
201
|
+
const raw = JSON.parse(readFileSync(portFilePath(root), "utf8"));
|
|
202
|
+
if (typeof raw.pid === "number" && raw.pid !== process.pid) {
|
|
203
|
+
// A previous process's record: safe to drop. The loopback socket it
|
|
204
|
+
// named cannot be trusted for reuse and is never dialled here.
|
|
205
|
+
rmSync(portFilePath(root), { force: true });
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
// Absent or unreadable state is fine; a fresh record gets written below.
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Starts (or returns) the sidecar for this dev-server process.
|
|
214
|
+
*
|
|
215
|
+
* `root` is the project root; the manifest names itself from it. The server
|
|
216
|
+
* binds 127.0.0.1 exclusively.
|
|
217
|
+
*/
|
|
218
|
+
export async function ensureSidecar(root, options = {}) {
|
|
219
|
+
// Watchers and removal events report REAL paths; on macOS the tmp/root
|
|
220
|
+
// prefix may differ (e.g. /tmp -> /private/tmp), so canonicalize once and
|
|
221
|
+
// derive every filesystem-relative computation from the canonical root.
|
|
222
|
+
const fsRoot = await realpath(root).catch(() => root);
|
|
223
|
+
const scanRoots = await tokenScanRoots(fsRoot, options.sourceRoots);
|
|
224
|
+
const state = globalState(`${options.tokens ? "tokens" : "manifest"}:${fsRoot}:${scanRoots.join("|")}`);
|
|
225
|
+
// The settled promise doubles as the handle cache: awaiting it replays the
|
|
226
|
+
// same handle for every caller until close/failure clears the slot.
|
|
227
|
+
if (state.starting)
|
|
228
|
+
return state.starting;
|
|
229
|
+
const starting = (async () => {
|
|
230
|
+
let generation = 0;
|
|
231
|
+
const streams = new Set();
|
|
232
|
+
// Token knowledge lives in a mutable holder so settled batches can swap
|
|
233
|
+
// the snapshot without rebuilding the rest of the manifest.
|
|
234
|
+
// Component contracts aggregate across loader postings, keyed by file so
|
|
235
|
+
// recompiles replace rather than duplicate (Stage 5). A debounced flush
|
|
236
|
+
// publishes one revision per settled burst of compilations.
|
|
237
|
+
const contractsByFile = new Map();
|
|
238
|
+
let contractsTimer = null;
|
|
239
|
+
const flushContracts = () => {
|
|
240
|
+
contractsTimer = null;
|
|
241
|
+
const flat = [];
|
|
242
|
+
for (const list of contractsByFile.values())
|
|
243
|
+
flat.push(...list);
|
|
244
|
+
// SAFETY: contracts come from the shared extractor or the loader's
|
|
245
|
+
// serialized output of that same extractor contract.
|
|
246
|
+
manifest.runtime.componentContracts = flat;
|
|
247
|
+
generation += 1;
|
|
248
|
+
for (const stream of streams) {
|
|
249
|
+
stream.write(`data: ${JSON.stringify({ revision: generation })}\n\n`);
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
const manifest = options.manifest ?? buildManifest({ root });
|
|
253
|
+
const additionalTokenRoots = scanRoots.filter((scanRoot) => scanRoot !== fsRoot);
|
|
254
|
+
const tokenSnapshotOptions = {
|
|
255
|
+
rootDirectory: fsRoot,
|
|
256
|
+
generationLabel: "nextjs-token",
|
|
257
|
+
...(additionalTokenRoots.length > 0 ? { additionalRootDirectories: additionalTokenRoots } : {}),
|
|
258
|
+
};
|
|
259
|
+
const applySnapshot = (snapshot) => {
|
|
260
|
+
manifest.runtime.tokenCatalog = snapshot.tokenCatalog;
|
|
261
|
+
manifest.runtime.tokens = snapshot.tokens;
|
|
262
|
+
manifest.runtime.tokenDiagnostics = snapshot.tokenDiagnostics;
|
|
263
|
+
manifest.runtime.tokenGeneration = snapshot.tokenGeneration;
|
|
264
|
+
};
|
|
265
|
+
const receiveContracts = (file, contracts) => {
|
|
266
|
+
contractsByFile.set(file, contracts);
|
|
267
|
+
if (!contractsTimer)
|
|
268
|
+
contractsTimer = setTimeout(flushContracts, 120);
|
|
269
|
+
};
|
|
270
|
+
const server = createServer((req, res) => {
|
|
271
|
+
respond(req, res, () => manifest, () => generation, streams, receiveContracts);
|
|
272
|
+
});
|
|
273
|
+
const port = await new Promise((resolvePort, rejectPort) => {
|
|
274
|
+
server.once("error", rejectPort);
|
|
275
|
+
// Port 0 asks the kernel for a free loopback port, so concurrent
|
|
276
|
+
// projects on one machine never collide.
|
|
277
|
+
server.listen(0, "127.0.0.1", () => {
|
|
278
|
+
const address = server.address();
|
|
279
|
+
if (address && typeof address === "object")
|
|
280
|
+
resolvePort(address.port);
|
|
281
|
+
else
|
|
282
|
+
rejectPort(new Error("nudge-ui sidecar failed to report its port"));
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
try {
|
|
286
|
+
mkdirSync(stateDirFor(root), { recursive: true });
|
|
287
|
+
writeFileSync(portFilePath(root), `${JSON.stringify({ pid: process.pid, port })}\n`);
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
// The port file is diagnostics-only; the rewrite carries the real
|
|
291
|
+
// transport, so an unwritable .next must not break instrumentation.
|
|
292
|
+
}
|
|
293
|
+
const watchers = [];
|
|
294
|
+
// The startup source scan runs regardless of the token lifecycle so a
|
|
295
|
+
// restarted sidecar republishes contracts even when Turbopack's
|
|
296
|
+
// persistent cache skips every loader re-run.
|
|
297
|
+
try {
|
|
298
|
+
await scanProjectContracts(fsRoot, (file, list) => {
|
|
299
|
+
contractsByFile.set(file, list);
|
|
300
|
+
});
|
|
301
|
+
if (contractsByFile.size > 0)
|
|
302
|
+
flushContracts();
|
|
303
|
+
}
|
|
304
|
+
catch {
|
|
305
|
+
/* an unreadable tree keeps whatever knowledge postings provided */
|
|
306
|
+
}
|
|
307
|
+
if (options.tokens) {
|
|
308
|
+
// Initial scan before the first manifest response so early clients see
|
|
309
|
+
// tokens without waiting for a watcher tick. Failures degrade to the
|
|
310
|
+
// empty snapshot already present in the manifest.
|
|
311
|
+
try {
|
|
312
|
+
applySnapshot(await createProjectTokenSnapshot(tokenSnapshotOptions));
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
/* keep empty snapshot */
|
|
316
|
+
}
|
|
317
|
+
generation += 1;
|
|
318
|
+
const settleTokens = async () => {
|
|
319
|
+
try {
|
|
320
|
+
applySnapshot(await createProjectTokenSnapshot(tokenSnapshotOptions));
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
/* unreadable trees keep the previous snapshot */
|
|
324
|
+
}
|
|
325
|
+
flushContracts();
|
|
326
|
+
};
|
|
327
|
+
const settleProjectChanges = async (changes) => {
|
|
328
|
+
let needsContractRescan = false;
|
|
329
|
+
// Changed or deleted component sources update their aggregated
|
|
330
|
+
// contracts directly: deletions must prune (or stale controls
|
|
331
|
+
// survive forever), and edits re-extract from the authored bytes
|
|
332
|
+
// even if a compiler cache never re-runs the loader. A read that
|
|
333
|
+
// lands mid-write is skipped — the next settled batch retries.
|
|
334
|
+
for (const change of changes) {
|
|
335
|
+
const normalized = change.absolutePath.split("\\").join("/");
|
|
336
|
+
// fs.watch can report a directory or omit a filename. In that
|
|
337
|
+
// case the exact source is unknown, so a bounded project scan is
|
|
338
|
+
// the only way to keep the contract catalog coherent.
|
|
339
|
+
if (!CONTRACT_SOURCE_EXT.test(normalized)) {
|
|
340
|
+
needsContractRescan = true;
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
const key = relative(fsRoot, normalized);
|
|
344
|
+
if (change.kind === "remove") {
|
|
345
|
+
contractsByFile.delete(key);
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
const stable = readStableSource(change.absolutePath);
|
|
349
|
+
if (!stable) {
|
|
350
|
+
needsContractRescan = true;
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
try {
|
|
354
|
+
contractsByFile.set(key, extractComponentContracts(stable.source, key));
|
|
355
|
+
}
|
|
356
|
+
catch {
|
|
357
|
+
/* syntactically invalid sources keep their previous knowledge */
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (needsContractRescan) {
|
|
361
|
+
const scannedContracts = new Map();
|
|
362
|
+
const scan = await scanProjectContracts(fsRoot, (file, list) => {
|
|
363
|
+
scannedContracts.set(file, list);
|
|
364
|
+
});
|
|
365
|
+
if (!scan.truncated) {
|
|
366
|
+
for (const file of contractsByFile.keys()) {
|
|
367
|
+
if (!scan.files.has(file))
|
|
368
|
+
contractsByFile.delete(file);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
for (const [file, list] of scannedContracts) {
|
|
372
|
+
contractsByFile.set(file, list);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
await settleTokens();
|
|
376
|
+
};
|
|
377
|
+
// Always keep the application watcher responsible for component
|
|
378
|
+
// contracts. Additional workspace roots only need token updates; using
|
|
379
|
+
// them for contract rescans would broaden the contract root silently.
|
|
380
|
+
// Roots nested inside the app are already covered by the app watcher.
|
|
381
|
+
const additionalRoots = scanRoots.filter((scanRoot) => scanRoot !== fsRoot && !isWithinRoot(fsRoot, scanRoot));
|
|
382
|
+
// Additional roots can overlap each other (for example an explicit
|
|
383
|
+
// source root inside the workspace). Keep only the outermost so one
|
|
384
|
+
// sibling edit settles into one token scan.
|
|
385
|
+
const outerAdditionalRoots = additionalRoots
|
|
386
|
+
.sort((a, b) => a.length - b.length)
|
|
387
|
+
.filter((scanRoot, index, list) => !list.slice(0, index).some((outer) => isWithinRoot(outer, scanRoot)));
|
|
388
|
+
const appWatcher = createProjectFileWatcher({
|
|
389
|
+
rootDirectory: fsRoot,
|
|
390
|
+
debounceMs: 60,
|
|
391
|
+
onSettled: settleProjectChanges,
|
|
392
|
+
});
|
|
393
|
+
await appWatcher.start();
|
|
394
|
+
watchers.push(appWatcher);
|
|
395
|
+
for (const tokenRoot of outerAdditionalRoots) {
|
|
396
|
+
const watcher = createProjectFileWatcher({
|
|
397
|
+
rootDirectory: tokenRoot,
|
|
398
|
+
debounceMs: 60,
|
|
399
|
+
onSettled: async (changes) => {
|
|
400
|
+
// A workspace root contains the app tree, so app edits fire this
|
|
401
|
+
// watcher too. The app watcher already refreshes tokens for those
|
|
402
|
+
// edits, so only changes outside the app need a second scan.
|
|
403
|
+
const outside = isWithinRoot(tokenRoot, fsRoot)
|
|
404
|
+
? changes.filter((change) => !isWithinRoot(fsRoot, change.absolutePath))
|
|
405
|
+
: changes;
|
|
406
|
+
if (outside.length === 0)
|
|
407
|
+
return;
|
|
408
|
+
await settleTokens();
|
|
409
|
+
},
|
|
410
|
+
});
|
|
411
|
+
await watcher.start();
|
|
412
|
+
watchers.push(watcher);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
const handle = {
|
|
416
|
+
port,
|
|
417
|
+
publishRevision(revision) {
|
|
418
|
+
generation = revision;
|
|
419
|
+
for (const stream of streams)
|
|
420
|
+
stream.write(`data: ${JSON.stringify({ revision })}\n\n`);
|
|
421
|
+
},
|
|
422
|
+
close() {
|
|
423
|
+
// Idempotent: the singleton handle can be reached from several test
|
|
424
|
+
// files in one worker, and a dev server shutdown may race an explicit
|
|
425
|
+
// close. Closing twice must not throw.
|
|
426
|
+
if (!server.listening) {
|
|
427
|
+
state.starting = undefined;
|
|
428
|
+
return Promise.resolve();
|
|
429
|
+
}
|
|
430
|
+
for (const stream of streams)
|
|
431
|
+
stream.end();
|
|
432
|
+
streams.clear();
|
|
433
|
+
void Promise.all(watchers.map((watcher) => watcher.close().catch(() => { })));
|
|
434
|
+
rmSync(portFilePath(root), { force: true });
|
|
435
|
+
state.starting = undefined;
|
|
436
|
+
return new Promise((resolveClose, rejectClose) => {
|
|
437
|
+
server.close((error) => (error ? rejectClose(error) : resolveClose()));
|
|
438
|
+
});
|
|
439
|
+
},
|
|
440
|
+
};
|
|
441
|
+
return handle;
|
|
442
|
+
})();
|
|
443
|
+
// A failed start must not wedge the singleton forever: the Symbol.for key
|
|
444
|
+
// survives HMR re-evaluation, so a cached rejected promise would be
|
|
445
|
+
// replayed to every later caller. Observe the rejection and clear the slot
|
|
446
|
+
// (identity-checked so a concurrent successful start is never discarded).
|
|
447
|
+
starting.catch(() => {
|
|
448
|
+
if (state.starting === starting)
|
|
449
|
+
state.starting = undefined;
|
|
450
|
+
});
|
|
451
|
+
state.starting = starting;
|
|
452
|
+
return starting;
|
|
453
|
+
}
|
|
454
|
+
function respond(req, res, currentManifest, currentGeneration, streams, receiveContracts) {
|
|
455
|
+
const url = (req.url ?? "").split("?")[0];
|
|
456
|
+
// Loader postings aggregate component contracts (Stage 5). Loopback-only by
|
|
457
|
+
// virtue of the bind address; payload size is capped defensively.
|
|
458
|
+
if (url === `${NUDGE_UI_ROUTE_PREFIX}contracts` && req.method === "POST") {
|
|
459
|
+
let body = "";
|
|
460
|
+
req.on("data", (chunk) => {
|
|
461
|
+
body += chunk;
|
|
462
|
+
if (body.length > 5 * 1024 * 1024)
|
|
463
|
+
req.destroy();
|
|
464
|
+
});
|
|
465
|
+
req.on("end", () => {
|
|
466
|
+
try {
|
|
467
|
+
// SAFETY: The JSON.parse result is validated by the typeof/Array.isArray guards below before use.
|
|
468
|
+
const parsed = JSON.parse(body);
|
|
469
|
+
if (typeof parsed.file !== "string" || !Array.isArray(parsed.contracts)) {
|
|
470
|
+
res.writeHead(400).end();
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
receiveContracts(parsed.file, parsed.contracts);
|
|
474
|
+
res.writeHead(204).end();
|
|
475
|
+
}
|
|
476
|
+
catch {
|
|
477
|
+
res.writeHead(400).end();
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
if (req.method !== "GET") {
|
|
483
|
+
res.writeHead(405).end();
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
if (url === NUDGE_UI_MANIFEST_PATH) {
|
|
487
|
+
// The served snapshot carries its revision so clients can reconcile
|
|
488
|
+
// against SSE notifications instead of guessing.
|
|
489
|
+
const body = `${JSON.stringify({ ...currentManifest(), revision: currentGeneration() })}\n`;
|
|
490
|
+
res.writeHead(200, {
|
|
491
|
+
"content-type": "application/json",
|
|
492
|
+
"cache-control": "no-store",
|
|
493
|
+
});
|
|
494
|
+
res.end(body);
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
if (url === NUDGE_UI_CLIENT_PATH) {
|
|
498
|
+
try {
|
|
499
|
+
inspectorClientPath ??= packageRequire.resolve("nudge-ui/internal/client");
|
|
500
|
+
const body = readFileSync(inspectorClientPath);
|
|
501
|
+
res.writeHead(200, {
|
|
502
|
+
"content-type": "text/javascript; charset=utf-8",
|
|
503
|
+
"cache-control": "no-cache",
|
|
504
|
+
});
|
|
505
|
+
res.end(body);
|
|
506
|
+
}
|
|
507
|
+
catch {
|
|
508
|
+
res.writeHead(503).end("Nudge UI client has not been built.");
|
|
509
|
+
}
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
if (url === NUDGE_UI_RELOAD_PATH) {
|
|
513
|
+
res.writeHead(200, {
|
|
514
|
+
"content-type": "text/event-stream",
|
|
515
|
+
"cache-control": "no-store",
|
|
516
|
+
connection: "keep-alive",
|
|
517
|
+
});
|
|
518
|
+
res.write(": nudge-ui reload stream\n\n");
|
|
519
|
+
streams.add(res);
|
|
520
|
+
res.on("close", () => streams.delete(res));
|
|
521
|
+
// Announce the current generation so late subscribers can reconcile.
|
|
522
|
+
res.write(`data: ${JSON.stringify({ revision: currentGeneration() })}\n\n`);
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
res.writeHead(404).end();
|
|
526
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { ComponentModuleProtocols } from "../../compiler/componentPolicyResolution.js";
|
|
2
|
+
/**
|
|
3
|
+
* `withNudgeUi(nextConfig)` — the single user touchpoint (ADR-0010).
|
|
4
|
+
*
|
|
5
|
+
* Development-phase gated per ADR-0002: the returned config factory
|
|
6
|
+
* instruments only `next dev` (`PHASE_DEVELOPMENT_SERVER` with
|
|
7
|
+
* `NODE_ENV=development`). Every other phase returns the original
|
|
8
|
+
* configuration untouched and nothing is registered, spawned, or injected.
|
|
9
|
+
* Production builds cannot observe Nudge UI.
|
|
10
|
+
*
|
|
11
|
+
* The wrapper is written against a structural subset of Next's config types
|
|
12
|
+
* so this package stays typecheckable without `next` installed; consumers
|
|
13
|
+
* pass their real NextConfig object straight through.
|
|
14
|
+
*/
|
|
15
|
+
/** Structural subset of Next.js config this wrapper reads and writes. */
|
|
16
|
+
export interface NudgeUiNextConfig {
|
|
17
|
+
[key: string]: unknown;
|
|
18
|
+
turbopack?: {
|
|
19
|
+
rules?: Record<string, unknown>;
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
};
|
|
22
|
+
webpack?: (config: Record<string, unknown>, context: {
|
|
23
|
+
dev: boolean;
|
|
24
|
+
[key: string]: unknown;
|
|
25
|
+
}) => Record<string, unknown>;
|
|
26
|
+
rewrites?: (() => Promise<RewritesShape> | RewritesShape) | RewritesShape;
|
|
27
|
+
transpilePackages?: string[];
|
|
28
|
+
}
|
|
29
|
+
/** Host-specific policy additions passed to the shared source compiler. */
|
|
30
|
+
export interface NudgeUiNextOptions {
|
|
31
|
+
readonly componentProtocols?: ComponentModuleProtocols;
|
|
32
|
+
/** Authored workspace directories outside the Next.js application root. */
|
|
33
|
+
readonly sourceRoots?: readonly string[];
|
|
34
|
+
}
|
|
35
|
+
export interface RewritesSource {
|
|
36
|
+
source: string;
|
|
37
|
+
destination: string;
|
|
38
|
+
[key: string]: unknown;
|
|
39
|
+
}
|
|
40
|
+
export interface RewritesShape {
|
|
41
|
+
beforeFiles?: RewritesSource[];
|
|
42
|
+
afterFiles?: RewritesSource[];
|
|
43
|
+
fallback?: RewritesSource[];
|
|
44
|
+
[key: string]: unknown;
|
|
45
|
+
}
|
|
46
|
+
/** Mirrors next/constants PHASE_DEVELOPMENT_SERVER. */
|
|
47
|
+
export declare const DEVELOPMENT_SERVER_PHASE = "phase-development-server";
|
|
48
|
+
/**
|
|
49
|
+
* Wraps a Next.js configuration with Nudge UI instrumentation.
|
|
50
|
+
*
|
|
51
|
+
* Two input forms are supported:
|
|
52
|
+
*
|
|
53
|
+
* - **Function form (recommended):** pass `(phase) => nextConfig`; the
|
|
54
|
+
* wrapper resolves and instruments ONLY for PHASE_DEVELOPMENT_SERVER, so
|
|
55
|
+
* `NODE_ENV=development next build` cannot register instrumentation
|
|
56
|
+
* (ADR-0002) regardless of environment tricks.
|
|
57
|
+
* - **Object form:** converted to a phase-aware config factory. This keeps
|
|
58
|
+
* the convenient `withNudgeUi(nextConfig)` invocation while ensuring Next
|
|
59
|
+
* supplies the phase before any instrumentation can be registered.
|
|
60
|
+
*
|
|
61
|
+
* @param config The application's existing configuration or a config factory.
|
|
62
|
+
* @returns A configuration (or factory) to export in its place.
|
|
63
|
+
*/
|
|
64
|
+
/** Function form: gates instrumentation on PHASE_DEVELOPMENT_SERVER. */
|
|
65
|
+
export declare function withNudgeUi<T extends object>(factory: (phase: string) => T, options?: NudgeUiNextOptions): (phase: string) => T;
|
|
66
|
+
/** Object form: returns a phase-aware Next.js config factory. */
|
|
67
|
+
export declare function withNudgeUi<T extends object>(config: T, options?: NudgeUiNextOptions): (phase: string) => T;
|