camox 0.44.0 → 0.45.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/dist/components/AuthGate.js +0 -6
- package/dist/components/DeviceSelector.js +96 -0
- package/dist/components/PlatformLabel.js +20 -24
- package/dist/core/components/lexical/HighlightNode.js +1 -1
- package/dist/core/components/lexical/InlineContentEditable.js +15 -19
- package/dist/core/components/lexical/InlineLexicalEditor.js +54 -74
- package/dist/core/components/lexical/InlineStylesPlugin.js +53 -53
- package/dist/core/components/lexical/MaxLengthPlugin.js +59 -0
- package/dist/core/components/lexical/SelectionBroadcaster.js +53 -54
- package/dist/core/components/lexical/SidebarLexicalEditor.js +322 -229
- package/dist/core/components/lexical/SummaryToggleGuard.js +42 -0
- package/dist/core/components/lexical/TextLinkPopover.js +169 -180
- package/dist/core/createApp.d.ts +241 -312
- package/dist/core/createApp.js +123 -29
- package/dist/core/createBlock.d.ts +5 -5
- package/dist/core/createBlock.js +385 -152
- package/dist/core/createCollection.d.ts +55 -0
- package/dist/core/createCollection.js +93 -0
- package/dist/core/createLayout.d.ts +197 -61
- package/dist/core/createLayout.js +114 -56
- package/dist/core/defineDocument.d.ts +3 -5
- package/dist/core/derivedRoutes.js +49 -1
- package/dist/core/dom.d.ts +13 -4
- package/dist/core/dom.js +44 -1
- package/dist/core/editing/BlockEditingRuntime.d.ts +16 -0
- package/dist/core/editing/BlockEditingRuntime.js +6 -15
- package/dist/core/editing/CompleteBlockEditingRuntime.js +28 -23
- package/dist/core/editing/createEditableBlock.d.ts +754 -633
- package/dist/core/editing/createEditableBlock.js +2113 -1066
- package/dist/core/editing/referenceWrites.js +51 -0
- package/dist/core/editing/useLatestRecord.js +90 -0
- package/dist/core/hooks/useArtifactHost.js +139 -0
- package/dist/core/hooks/useFieldSelection.js +43 -18
- package/dist/core/hooks/useIsEditable.js +12 -10
- package/dist/core/hooks/useOverlayMessage.js +15 -19
- package/dist/core/lib/artifact.d.ts +21 -0
- package/dist/core/lib/artifact.js +154 -0
- package/dist/core/lib/artifactColors.js +123 -0
- package/dist/core/lib/artifactData.d.ts +1 -0
- package/dist/core/lib/artifactData.js +131 -0
- package/dist/core/lib/artifactHost.js +205 -0
- package/dist/core/lib/artifactRuntime.js +36 -0
- package/dist/core/lib/artifactTheme.js +57 -0
- package/dist/core/lib/contentType.d.ts +302 -106
- package/dist/core/lib/contentType.js +201 -173
- package/dist/core/lib/fieldTypes.js +3 -0
- package/dist/core/lib/iconTypes.d.ts +3 -3
- package/dist/core/lib/icons.d.ts +4 -4
- package/dist/core/lib/icons.js +40 -44
- package/dist/core/lib/imagePlaceholder.js +177 -0
- package/dist/core/lib/imageTransform.js +1 -1
- package/dist/core/lib/lexicalReact.d.ts +3 -1
- package/dist/core/lib/lexicalState.js +1 -1
- package/dist/core/lib/previewPaused.js +9 -0
- package/dist/core/lib/recordScope.js +316 -0
- package/dist/core/lib/reference.d.ts +81 -0
- package/dist/core/lib/reference.js +29 -0
- package/dist/core/lib/textLinks.js +7 -5
- package/dist/core/lib/textStyles.d.ts +5 -7
- package/dist/core/lib/textStyles.js +2 -2
- package/dist/core/notFound.d.ts +7 -0
- package/dist/core/notFound.js +11 -0
- package/dist/core/pageDestinations.js +6 -3
- package/dist/core/recordItem.js +34 -0
- package/dist/core/requestContext.d.ts +26 -0
- package/dist/core/requestContext.js +20 -0
- package/dist/features/canvas/CamoxCanvas.js +1734 -0
- package/dist/features/canvas/CanvasBlockFrame.js +353 -0
- package/dist/features/canvas/CanvasBlockHeader.js +55 -0
- package/dist/features/canvas/CanvasLoadingScreen.js +35 -0
- package/dist/features/canvas/CanvasOverlays.js +254 -0
- package/dist/features/canvas/CanvasPageEdge.js +87 -0
- package/dist/features/canvas/CanvasPageFrame.js +335 -0
- package/dist/features/canvas/CanvasPageHeader.js +125 -0
- package/dist/features/canvas/CanvasPreviewPageSlot.js +103 -0
- package/dist/features/canvas/CanvasShelfMarker.js +255 -0
- package/dist/features/canvas/DerivedPagePathInput.js +238 -0
- package/dist/features/canvas/canvasCamera.js +229 -0
- package/dist/features/canvas/canvasFlight.js +104 -0
- package/dist/features/canvas/canvasFrameCapture.js +364 -0
- package/dist/features/canvas/canvasFrameDocument.js +317 -0
- package/dist/features/canvas/canvasFrameMode.js +53 -0
- package/dist/features/canvas/canvasInsertionSeams.js +44 -0
- package/dist/features/canvas/canvasItems.js +120 -0
- package/dist/features/canvas/canvasOverlayGeometry.js +240 -0
- package/dist/features/canvas/canvasPages.js +79 -0
- package/dist/features/canvas/canvasScreenSpace.js +26 -0
- package/dist/features/canvas/canvasSelection.js +18 -0
- package/dist/features/canvas/canvasStore.js +149 -0
- package/dist/features/canvas/canvasThumbnails.js +304 -0
- package/dist/features/canvas/canvasZoom.js +10 -0
- package/dist/features/canvas/sidebar/CanvasInspector.js +202 -0
- package/dist/features/canvas/sidebar/CanvasNavigator.js +226 -0
- package/dist/features/canvas/sidebar/CanvasSidebar.js +60 -0
- package/dist/features/canvas/sidebar/CanvasSidebarFrame.js +48 -0
- package/dist/features/canvas/sidebar/CanvasSidebarSkeleton.js +39 -0
- package/dist/features/canvas/sidebar/CatalogBlockInspector.js +189 -0
- package/dist/features/canvas/sidebar/CuratedPageInspector.js +69 -0
- package/dist/features/canvas/sidebar/DerivedPageInspector.js +37 -0
- package/dist/features/canvas/sidebar/LayoutPageBlocks.js +78 -0
- package/dist/features/canvas/sidebar/LayoutPageOverview.js +71 -0
- package/dist/features/canvas/sidebar/PageInspector.js +157 -0
- package/dist/features/canvas/sidebar/PageInspectorSkeleton.js +90 -0
- package/dist/features/canvas/sidebar/PageOverview.js +27 -0
- package/dist/features/canvas/sidebar/SingletonPageInspector.js +31 -0
- package/dist/features/canvas/useCanvasCamera.js +803 -0
- package/dist/features/canvas/useCanvasFrame.js +149 -0
- package/dist/features/canvas/useCanvasFrameInput.js +97 -0
- package/dist/features/canvas/useCanvasNearness.js +57 -0
- package/dist/features/canvas/useDiscoveredPreviewPaths.js +62 -0
- package/dist/features/content/CamoxContent.d.ts +2 -5
- package/dist/features/content/CamoxContent.js +174 -271
- package/dist/features/content/CollectionItemSheetContext.js +106 -0
- package/dist/features/content/ContentAssets.js +315 -0
- package/dist/features/content/ContentCollection.js +663 -0
- package/dist/features/content/collection-form.js +58 -0
- package/dist/features/content/components/AssetCard.js +80 -84
- package/dist/features/content/components/AssetCardSkeleton.js +4 -8
- package/dist/features/content/components/ContentSidebar.js +129 -18
- package/dist/features/content/components/ContentSidebarGroup.js +37 -0
- package/dist/features/content/components/DeleteCollectionItemButton.js +202 -0
- package/dist/features/content/components/MissingFromLocale.js +282 -0
- package/dist/features/content/components/UploadDropZone.js +27 -31
- package/dist/features/content/components/UploadProgressDrawer.js +90 -98
- package/dist/features/navigation/navigation.d.ts +66 -20
- package/dist/features/navigation/navigation.js +257 -90
- package/dist/features/og/defaultFonts.js +8 -8
- package/dist/features/og/geist-variable-ttf-base64.js +1 -1
- package/dist/features/og/imageResponse.d.ts +8 -0
- package/dist/features/og/imageResponse.js +26 -0
- package/dist/features/page/CuratedPageContent.js +167 -0
- package/dist/features/page/DerivedPageContent.js +26 -30
- package/dist/features/page/SharedLayoutContent.js +25 -27
- package/dist/features/preview/CamoxPreview.d.ts +23 -61
- package/dist/features/preview/CamoxPreview.js +816 -537
- package/dist/features/preview/EditablePageContent.js +1 -1
- package/dist/features/preview/EditablePageExperience.js +16 -22
- package/dist/features/preview/components/AddBlockDialog.js +270 -0
- package/dist/features/preview/components/AssetFieldEditor.js +173 -154
- package/dist/features/preview/components/AssetLightbox.js +181 -134
- package/dist/features/preview/components/AssetPickerModal.js +153 -170
- package/dist/features/preview/components/BlockActionsPopover.js +150 -149
- package/dist/features/preview/components/BlockErrorBoundary.js +8 -12
- package/dist/features/preview/components/BlockThumbnail.js +176 -100
- package/dist/features/preview/components/CanvasPreview.js +243 -0
- package/dist/features/preview/components/CreatePageModal.js +128 -137
- package/dist/features/preview/components/DebouncedFieldEditor.js +29 -33
- package/dist/features/preview/components/DerivedLayoutDialog.js +21 -19
- package/dist/features/preview/components/DrillRow.js +150 -0
- package/dist/features/preview/components/FieldOverlayStyles.js +11 -8
- package/dist/features/preview/components/FieldToolbar.js +160 -110
- package/dist/features/preview/components/Frame.js +108 -20
- package/dist/features/preview/components/IconFieldEditor.js +62 -66
- package/dist/features/preview/components/ItemFieldsEditor.js +231 -205
- package/dist/features/preview/components/LinkFieldEditor.js +135 -139
- package/dist/features/preview/components/Metadata.js +22 -30
- package/dist/features/preview/components/MobilePreviewDrawer.js +89 -108
- package/dist/features/preview/components/MultipleAssetFieldEditor.js +334 -246
- package/dist/features/preview/components/OverlayTracker.js +9 -41
- package/dist/features/preview/components/Overlays.js +81 -69
- package/dist/features/preview/components/PageInfo.js +1748 -0
- package/dist/features/preview/components/PageInfoSkeleton.js +51 -0
- package/dist/features/preview/components/PageLocationFieldset.js +112 -116
- package/dist/features/preview/components/PageNavigatorHeader.js +24 -0
- package/dist/features/preview/components/PageNicknameField.js +22 -26
- package/dist/features/preview/components/PagePicker.js +128 -130
- package/dist/features/preview/components/PageTree.js +525 -532
- package/dist/features/preview/components/PreviewActivation.js +28 -32
- package/dist/features/preview/components/PreviewPanel.js +620 -319
- package/dist/features/preview/components/PreviewToolbar.js +105 -333
- package/dist/features/preview/components/RecordCard.js +80 -0
- package/dist/features/preview/components/RecordCombobox.js +178 -0
- package/dist/features/preview/components/ReferenceFieldEditor.js +149 -0
- package/dist/features/preview/components/ReferenceListFieldEditor.js +432 -0
- package/dist/features/preview/components/RemovedBlockPlaceholder.js +95 -0
- package/dist/features/preview/components/RepeatableItemsList.js +125 -138
- package/dist/features/preview/components/SelectionEditor.js +993 -0
- package/dist/features/preview/components/ShikiMarkdown.js +14 -18
- package/dist/features/preview/components/SidebarSection.js +52 -64
- package/dist/features/preview/components/StudioEditingFallback.js +56 -0
- package/dist/features/preview/components/UnlinkAssetButton.js +104 -107
- package/dist/features/preview/components/blockGridNavigation.js +15 -0
- package/dist/features/preview/components/contentFieldSchema.js +8 -0
- package/dist/features/preview/components/useFieldWriter.js +200 -0
- package/dist/features/preview/components/useRecordView.js +383 -0
- package/dist/features/preview/components/useRepeatableItemActions.js +35 -37
- package/dist/features/preview/components/useUpdateBlockPosition.js +37 -37
- package/dist/features/preview/editingFrame.js +197 -0
- package/dist/features/preview/overlayHighlights.js +17 -44
- package/dist/features/preview/overlayMessages.js +72 -1
- package/dist/features/preview/pageRecord.js +189 -0
- package/dist/features/preview/previewConstants.js +6 -2
- package/dist/features/preview/previewPageFrame.js +95 -0
- package/dist/features/preview/previewPreparation.js +7 -0
- package/dist/features/preview/previewSelection.js +32 -63
- package/dist/features/preview/previewStore.js +225 -123
- package/dist/features/preview/referencePickerFocus.js +29 -0
- package/dist/features/preview/repeatableItemTargets.js +56 -0
- package/dist/features/preview/selectionReveal.js +21 -0
- package/dist/features/preview/usePreviewViewportActions.js +114 -0
- package/dist/features/preview/viewportContinuity.js +109 -0
- package/dist/features/provider/AuthenticatedCamoxProvider.js +69 -44
- package/dist/features/provider/CamoxProvider.d.ts +3 -6
- package/dist/features/provider/CamoxProvider.js +38 -50
- package/dist/features/provider/CoreCamoxProvider.js +66 -50
- package/dist/features/provider/LocalhostPreviewProvider.js +78 -114
- package/dist/features/provider/PreviewSignInPage.js +54 -0
- package/dist/features/provider/components/CamoxAppContext.js +11 -11
- package/dist/features/provider/components/CommandPalette.js +75 -82
- package/dist/features/provider/useAdminShortcuts.js +7 -11
- package/dist/features/routes/pageRuntime.d.ts +44 -4
- package/dist/features/routes/pageRuntime.js +244 -137
- package/dist/features/runtime/RuntimeChrome.js +117 -115
- package/dist/features/runtime/alternates.js +64 -0
- package/dist/features/runtime/analytics.d.ts +7 -0
- package/dist/features/runtime/analytics.js +66 -0
- package/dist/features/runtime/artifactSources.js +87 -0
- package/dist/features/runtime/editingFallback.js +20 -0
- package/dist/features/runtime/linkPrefetch.js +97 -0
- package/dist/features/runtime/livePages.js +62 -0
- package/dist/features/runtime/llmsTxt.js +40 -0
- package/dist/features/runtime/loopbackFetch.js +18 -0
- package/dist/features/runtime/navigationAccessibility.js +51 -0
- package/dist/features/runtime/navigationTarget.js +23 -2
- package/dist/features/runtime/pageApp.js +229 -158
- package/dist/features/runtime/pageBlockTypes.js +20 -0
- package/dist/features/runtime/pageClient.d.ts +2 -4
- package/dist/features/runtime/pageClient.js +18 -3
- package/dist/features/runtime/pageNavigation.js +254 -32
- package/dist/features/runtime/pageServer.d.ts +2 -4
- package/dist/features/runtime/pageServer.js +6 -2
- package/dist/features/runtime/pageViewport.js +7 -0
- package/dist/features/runtime/runtime.d.ts +59 -24
- package/dist/features/runtime/runtime.js +779 -191
- package/dist/features/runtime/runtimeChromeLoader.js +58 -0
- package/dist/features/runtime/runtimeRoutes.d.ts +19 -0
- package/dist/features/runtime/runtimeRoutes.js +25 -0
- package/dist/features/runtime/scrollRestoration.js +133 -0
- package/dist/features/runtime/studioApp.d.ts +4 -3
- package/dist/features/runtime/studioApp.js +5 -9
- package/dist/features/runtime/studioClient.d.ts +2 -4
- package/dist/features/runtime/studioClient.js +12 -3
- package/dist/features/runtime/studioServer.d.ts +2 -4
- package/dist/features/runtime/studioServer.js +6 -1
- package/dist/features/runtime/worker.d.ts +6 -0
- package/dist/features/runtime/worker.js +23 -0
- package/dist/features/runtime/workerRequest.js +44 -0
- package/dist/features/studio/CamoxStudio.d.ts +2 -6
- package/dist/features/studio/CamoxStudio.js +34 -49
- package/dist/features/studio/FollowAgentProvider.js +338 -0
- package/dist/features/studio/components/ChatSidebar.js +356 -0
- package/dist/features/studio/components/DraftsControl.js +676 -0
- package/dist/features/studio/components/FaviconDialog.js +318 -0
- package/dist/features/studio/components/LocalePicker.js +785 -0
- package/dist/features/studio/components/Navbar.js +123 -103
- package/dist/features/studio/components/ProjectMenu.js +239 -260
- package/dist/features/studio/components/RenameDraftDialog.js +206 -0
- package/dist/features/studio/components/ReviewDraftSheet.js +1472 -0
- package/dist/features/studio/components/ThreadComposer.js +157 -0
- package/dist/features/studio/components/ThreadMarkdown.js +113 -0
- package/dist/features/studio/components/ThreadMessages.js +270 -0
- package/dist/features/studio/components/UserButton.js +34 -23
- package/dist/features/studio/draftLabel.js +33 -0
- package/dist/features/studio/draftNotice.js +13 -0
- package/dist/features/studio/followAgent.js +250 -0
- package/dist/features/studio/followAgentContext.js +7 -0
- package/dist/features/studio/localeOptions.js +118 -0
- package/dist/features/studio/localeSwitch.js +19 -0
- package/dist/features/studio/routes.js +48 -1
- package/dist/features/studio/studioStore.js +64 -1
- package/dist/features/studio/useTheme.js +24 -27
- package/dist/features/vite/artifactRuntimeMinification.js +36 -0
- package/dist/features/vite/blockBoilerplate.js +6 -5
- package/dist/features/vite/blockChunks.js +31 -0
- package/dist/features/vite/bundlerLogs.js +17 -0
- package/dist/features/vite/definitionsSync.js +158 -226
- package/dist/features/vite/devAuthentication.js +4 -16
- package/dist/features/vite/devSignIn.js +87 -0
- package/dist/features/vite/iconGeneration.js +1 -1
- package/dist/features/vite/layoutGeneration.js +11 -1
- package/dist/features/vite/publishSeededContent.js +30 -0
- package/dist/features/vite/routeGeneration.js +6 -7
- package/dist/features/vite/runtimeDev.js +80 -99
- package/dist/features/vite/vite.d.ts +51 -31
- package/dist/features/vite/vite.js +224 -127
- package/dist/features/vite/workerBuild.js +39 -0
- package/dist/hooks/use-debounced-field.js +116 -47
- package/dist/hooks/use-file-upload.js +114 -67
- package/dist/hooks/use-marquee-selection.js +32 -36
- package/dist/hooks/use-page-destinations.js +69 -37
- package/dist/lib/api-client-server.d.ts +5 -0
- package/dist/lib/api-client-server.js +10 -4
- package/dist/lib/api-client.d.ts +6 -0
- package/dist/lib/api-client.js +51 -16
- package/dist/lib/api-socket.js +17 -0
- package/dist/lib/auth-page-styles.js +39 -0
- package/dist/lib/auth.js +117 -61
- package/dist/lib/collection-cache.js +23 -0
- package/dist/lib/draft-scope.d.ts +4 -0
- package/dist/lib/draft-scope.js +222 -0
- package/dist/lib/html.js +12 -0
- package/dist/lib/link-pages.js +154 -0
- package/dist/lib/locale-path.d.ts +22 -0
- package/dist/lib/locale-path.js +57 -0
- package/dist/lib/normalized-data.js +252 -152
- package/dist/lib/preview-handoff.js +2 -2
- package/dist/lib/queries.d.ts +11 -0
- package/dist/lib/queries.js +70 -141
- package/dist/lib/studio-reads.d.ts +14 -0
- package/dist/lib/studio-reads.js +574 -0
- package/dist/lib/use-project-room.js +50 -50
- package/dist/lib/use-thread.js +310 -0
- package/dist/lib/utils.js +25 -29
- package/dist/lib/view-locale-context.js +22 -0
- package/dist/lib/view-locale.js +46 -0
- package/dist/package.js +5 -0
- package/dist/studio-overlays.css +41 -151
- package/dist/studio.css +2 -2
- package/package.json +70 -73
- package/skills/camox/SKILL.md +16 -11
- package/skills/camox/references/artifacts.md +179 -0
- package/skills/camox/references/block-definitions.md +75 -59
- package/skills/camox/references/cli-common.md +9 -11
- package/skills/camox/references/cli-content.md +92 -69
- package/skills/camox/references/cli-publishing.md +26 -0
- package/skills/camox/references/dom-integrations.md +27 -0
- package/skills/camox/references/field-styling.md +4 -4
- package/skills/camox/references/layout-definitions.md +16 -14
- package/skills/camox/references/localization.md +56 -0
- package/skills/camox/references/routed-layouts.md +133 -15
- package/skills/camox-expand/SKILL.md +69 -0
- package/skills/camox-expand/references/jobs.md +39 -0
- package/skills/camoxify/SKILL.md +29 -7
- package/dist/core/components/AddBlockControlBar.js +0 -78
- package/dist/core/hooks/useRequireDraftSource.js +0 -23
- package/dist/features/metadata/sitemap.d.ts +0 -8
- package/dist/features/metadata/sitemap.js +0 -17
- package/dist/features/og/imageResponse.node.d.ts +0 -12
- package/dist/features/og/imageResponse.node.js +0 -49
- package/dist/features/og/imageResponse.workerd.d.ts +0 -12
- package/dist/features/og/imageResponse.workerd.js +0 -40
- package/dist/features/page/PublishedPageContent.js +0 -205
- package/dist/features/page/PublishedPageExperience.js +0 -23
- package/dist/features/preview/DerivedPreview.js +0 -134
- package/dist/features/preview/commentsEnabled.js +0 -8
- package/dist/features/preview/components/AddBlockSidebar.js +0 -381
- package/dist/features/preview/components/AttachedComments.js +0 -331
- package/dist/features/preview/components/CommentHeader.js +0 -122
- package/dist/features/preview/components/CommentSidebar.js +0 -29
- package/dist/features/preview/components/CommentTargetQuote.js +0 -167
- package/dist/features/preview/components/DerivedLayoutSidebar.d.ts +0 -5
- package/dist/features/preview/components/DerivedLayoutSidebar.js +0 -179
- package/dist/features/preview/components/DerivedPageInfoSidebar.js +0 -69
- package/dist/features/preview/components/LeftSidebar.js +0 -68
- package/dist/features/preview/components/PageEditorSidebar.js +0 -563
- package/dist/features/preview/components/PageInfoSidebar.js +0 -1551
- package/dist/features/preview/components/PageNavigatorSidebar.js +0 -78
- package/dist/features/preview/components/PageStatusBadge.js +0 -97
- package/dist/features/preview/components/PeekedBlock.js +0 -217
- package/dist/features/preview/components/PreviewComments.js +0 -56
- package/dist/features/preview/components/PreviewToolbarSpacer.js +0 -43
- package/dist/features/preview/components/PublicationRow.js +0 -422
- package/dist/features/preview/components/PublishDialog.js +0 -194
- package/dist/features/preview/components/RightSidebar.js +0 -59
- package/dist/features/preview/components/SendFeedbackDialog.js +0 -83
- package/dist/features/preview/previewCommentsStore.js +0 -135
- package/dist/features/preview/publication.js +0 -81
- package/dist/features/preview/usePageComments.js +0 -39
- package/dist/features/runtime/SharedChromeContext.js +0 -7
- package/dist/features/studio/components/EnvironmentMenu.js +0 -425
- package/dist/features/vite/appGeneration.js +0 -89
- package/dist/lib/view-queries.js +0 -28
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/Matches.d.ts +0 -114
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/RouterProvider.d.ts +0 -25
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/config.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/defer.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/fileRoute.d.ts +0 -20
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/global.d.ts +0 -8
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/hash-scroll.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/index.d.ts +0 -18
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/link.d.ts +0 -161
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/load-matches.d.ts +0 -6
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/location.d.ts +0 -54
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/lru-cache.d.ts +0 -8
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/manifest.d.ts +0 -32
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/new-process-route-tree.d.ts +0 -115
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/not-found.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/redirect.d.ts +0 -49
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/rewrite.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/root.d.ts +0 -6
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/route.d.ts +0 -343
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/routeInfo.d.ts +0 -48
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/router.d.ts +0 -695
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/scroll-restoration.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/searchMiddleware.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/searchParams.d.ts +0 -5
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/ssr/serializer/RawStream.d.ts +0 -38
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/ssr/serializer/seroval-plugins.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/ssr/serializer/transformer.d.ts +0 -65
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/stores.d.ts +0 -69
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/structuralSharing.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/typePrimitives.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/useLoaderData.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/useLoaderDeps.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/useNavigate.d.ts +0 -10
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/useParams.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/useRouteContext.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/useSearch.d.ts +0 -1
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/utils.d.ts +0 -28
- package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/validators.d.ts +0 -49
- package/skills/camox/references/cli-environments.md +0 -37
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { relative } from "node:path";
|
|
2
|
+
|
|
3
|
+
//#region src/features/vite/blockChunks.ts
|
|
4
|
+
const BLOCK_MODULE = /^src\/(camox\/)?blocks\/[^/]+\.tsx?$/;
|
|
5
|
+
/**
|
|
6
|
+
* The chunks the browser must load to render each block, by the block's module path (as the
|
|
7
|
+
* app's globs name it). Chunks every entry already loads are left out: they need no preload.
|
|
8
|
+
*/
|
|
9
|
+
function collectBlockChunks(bundle, root) {
|
|
10
|
+
const chunks = /* @__PURE__ */ new Map();
|
|
11
|
+
for (const output of Object.values(bundle)) if (output.type === "chunk") chunks.set(output.fileName, output);
|
|
12
|
+
const withImports = (fileName, into = /* @__PURE__ */ new Set()) => {
|
|
13
|
+
if (into.has(fileName)) return into;
|
|
14
|
+
into.add(fileName);
|
|
15
|
+
for (const imported of chunks.get(fileName)?.imports ?? []) withImports(imported, into);
|
|
16
|
+
return into;
|
|
17
|
+
};
|
|
18
|
+
const loadedByEntries = /* @__PURE__ */ new Set();
|
|
19
|
+
for (const chunk of chunks.values()) if (chunk.isEntry) withImports(chunk.fileName, loadedByEntries);
|
|
20
|
+
const blockChunks = {};
|
|
21
|
+
for (const chunk of chunks.values()) {
|
|
22
|
+
if (!chunk.isDynamicEntry || !chunk.facadeModuleId) continue;
|
|
23
|
+
const modulePath = relative(root, chunk.facadeModuleId).replaceAll("\\", "/");
|
|
24
|
+
if (!BLOCK_MODULE.test(modulePath)) continue;
|
|
25
|
+
blockChunks[`/${modulePath}`] = [...withImports(chunk.fileName)].filter((fileName) => !loadedByEntries.has(fileName));
|
|
26
|
+
}
|
|
27
|
+
return blockChunks;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
//#endregion
|
|
31
|
+
export { collectBlockChunks };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/features/vite/bundlerLogs.ts
|
|
2
|
+
/** Wraps the app's own `onLog`, if any, so it never sees warnings every Camox app produces. */
|
|
3
|
+
function withoutExpectedCamoxLogs(onLog) {
|
|
4
|
+
return (level, log, handler) => {
|
|
5
|
+
if (isExpectedCamoxLog(log)) return;
|
|
6
|
+
if (onLog) return onLog(level, log, handler);
|
|
7
|
+
handler(level, log);
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function isExpectedCamoxLog(log) {
|
|
11
|
+
if (log.code === "MODULE_LEVEL_DIRECTIVE") return log.message.includes("\"use client\"");
|
|
12
|
+
if (log.code === "INEFFECTIVE_DYNAMIC_IMPORT") return log.message.includes("virtual:camox/app");
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
export { withoutExpectedCamoxLogs };
|
|
@@ -1,279 +1,211 @@
|
|
|
1
1
|
import { createServerApiClient } from "../../lib/api-client-server.js";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import { DEVELOPMENT_DRAFT } from "@camox/api-contract/drafts";
|
|
3
|
+
import { isRunnableDevEnvironment } from "vite-plus";
|
|
4
4
|
|
|
5
5
|
//#region src/features/vite/definitionsSync.ts
|
|
6
6
|
const SYNC_DEBOUNCE_DELAY_MS = 100;
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* The client definitions sync with. A release (deploy token) syncs Live's definitions; dev mode
|
|
9
|
+
* sends the developer's session and syncs their development draft, which its first sync
|
|
10
|
+
* creates (ADR 0006).
|
|
10
11
|
*/
|
|
12
|
+
function createSyncClient(options) {
|
|
13
|
+
const draftId = options.deployToken ? void 0 : DEVELOPMENT_DRAFT;
|
|
14
|
+
return createServerApiClient(options.apiUrl, options.authToken, draftId);
|
|
15
|
+
}
|
|
11
16
|
function throwIfSyncAuthError(error) {
|
|
12
17
|
if (error instanceof Error && error.name === "ORPCError" && error.message.toLowerCase().includes("unauthorized")) throw new Error("[camox] Definition sync failed: invalid or missing credentials.");
|
|
13
18
|
}
|
|
14
19
|
function isNotFoundError(error) {
|
|
15
20
|
return error instanceof Error && error.name === "ORPCError" && error.message.toLowerCase().includes("not found");
|
|
16
21
|
}
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
/**
|
|
23
|
+
* A sync that may not create the development draft finds nothing to write to: a release names a
|
|
24
|
+
* project that doesn't exist, or dev mode has no development draft yet (ADR 0006).
|
|
25
|
+
*/
|
|
26
|
+
function throwSyncTargetNotFoundError(projectUuid, deployToken) {
|
|
27
|
+
if (deployToken) throw new Error(`[camox] No project has the Project ID "${projectUuid}". Check the camox() projectId.`);
|
|
28
|
+
throw new Error(`[camox] You have no development draft in the project with Project ID "${projectUuid}" yet. Run the dev server while authenticated to create it first.`);
|
|
29
|
+
}
|
|
30
|
+
/** `count` of `noun`, pluralized: "1 block", "2 blocks". */
|
|
31
|
+
function counted(count, noun) {
|
|
32
|
+
return `${count} ${noun}${count === 1 ? "" : "s"}`;
|
|
33
|
+
}
|
|
34
|
+
/** Names quoted and listed: `"hero", "footer"`. */
|
|
35
|
+
function quoted(names) {
|
|
36
|
+
return names.map((name) => `"${name}"`).join(", ");
|
|
19
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Send a Definition Set to the API: Live's for a release, the development draft's in dev mode.
|
|
40
|
+
* It goes in one `definitions.sync` call, which either fully applies it or changes nothing.
|
|
41
|
+
*/
|
|
20
42
|
async function syncDefinitionsToApi(options) {
|
|
21
|
-
const {
|
|
22
|
-
const client =
|
|
23
|
-
|
|
24
|
-
const layoutDefinitions = camoxApp.getSerializableLayoutDefinitions();
|
|
25
|
-
const typesUsedInLayouts = /* @__PURE__ */ new Set();
|
|
26
|
-
for (const layout of layoutDefinitions) for (const blockDef of layout.blocks) typesUsedInLayouts.add(blockDef.type);
|
|
27
|
-
const definitions = blocks.filter((block) => !block._internal.layoutOnly || typesUsedInLayouts.has(block._internal.id)).map((block) => ({
|
|
28
|
-
blockId: block._internal.id,
|
|
29
|
-
title: block._internal.title,
|
|
30
|
-
description: block._internal.description,
|
|
31
|
-
contentSchema: block._internal.contentSchema,
|
|
32
|
-
settingsSchema: block._internal.settingsSchema,
|
|
33
|
-
defaultContent: block._internal.getInitialContent(),
|
|
34
|
-
defaultSettings: block._internal.getInitialSettings(),
|
|
35
|
-
layoutOnly: block._internal.layoutOnly || void 0,
|
|
36
|
-
synced: block._internal.synced
|
|
37
|
-
}));
|
|
38
|
-
let environmentCreated = false;
|
|
39
|
-
let deletedDefinitionTypes = [];
|
|
40
|
-
let blockedDefinitionDeletions = [];
|
|
43
|
+
const { definitionSet, projectUuid, autoCreate, deployToken, logger } = options;
|
|
44
|
+
const client = createSyncClient(options);
|
|
45
|
+
let result;
|
|
41
46
|
try {
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
result = await client.definitions.sync({
|
|
48
|
+
projectUuid,
|
|
44
49
|
deployToken,
|
|
45
50
|
autoCreate,
|
|
46
|
-
|
|
51
|
+
definitionSet
|
|
47
52
|
});
|
|
48
|
-
environmentCreated = result.environmentCreated;
|
|
49
|
-
deletedDefinitionTypes = result.deletedDefinitionTypes;
|
|
50
|
-
blockedDefinitionDeletions = result.blockedDefinitionDeletions;
|
|
51
53
|
} catch (error) {
|
|
52
54
|
throwIfSyncAuthError(error);
|
|
53
|
-
if (!autoCreate && isNotFoundError(error))
|
|
55
|
+
if (!autoCreate && isNotFoundError(error)) throwSyncTargetNotFoundError(projectUuid, deployToken);
|
|
54
56
|
throw error;
|
|
55
57
|
}
|
|
56
|
-
if (
|
|
57
|
-
logger.info(`[camox] Synced ${
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
layouts: layoutDefinitions
|
|
71
|
-
});
|
|
72
|
-
} catch (error) {
|
|
73
|
-
throwIfSyncAuthError(error);
|
|
74
|
-
if (!autoCreate && isNotFoundError(error)) throwUnknownEnvironmentError(environmentName);
|
|
75
|
-
throw error;
|
|
76
|
-
}
|
|
77
|
-
logger.info(`[camox] Synced ${layoutDefinitions.length} layout${layoutDefinitions.length === 1 ? "" : "s"} to Camox API`, { timestamp: true });
|
|
78
|
-
for (const result of layoutSyncResults.layouts) {
|
|
79
|
-
if (result.wasExisting && result.createdBlockTypes.length > 0) {
|
|
80
|
-
const blockList = result.createdBlockTypes.map((t) => `"${t}"`).join(", ");
|
|
81
|
-
logger.info(`[camox] Added ${result.createdBlockTypes.length} block${result.createdBlockTypes.length === 1 ? "" : "s"} to existing layout "${result.layout.layoutId}": ${blockList}`, { timestamp: true });
|
|
82
|
-
}
|
|
83
|
-
if (result.removedBlockTypes.length > 0) {
|
|
84
|
-
const blockList = result.removedBlockTypes.map((t) => `"${t}"`).join(", ");
|
|
85
|
-
logger.info(`[camox] Removed ${result.removedBlockTypes.length} layoutOnly block${result.removedBlockTypes.length === 1 ? "" : "s"} from layout "${result.layout.layoutId}": ${blockList}`, { timestamp: true });
|
|
86
|
-
}
|
|
87
|
-
if (result.skippedOrphanTypes.length > 0) {
|
|
88
|
-
const blockList = result.skippedOrphanTypes.map((t) => `"${t}"`).join(", ");
|
|
89
|
-
logger.info(`[camox] Layout "${result.layout.layoutId}" has ${result.skippedOrphanTypes.length} block${result.skippedOrphanTypes.length === 1 ? "" : "s"} still in DB but removed from code: ${blockList} (kept because not layoutOnly)`, { timestamp: true });
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
for (const layoutId of layoutSyncResults.deletedLayoutIds) logger.info(`[camox] Deleted layout "${layoutId}"`, { timestamp: true });
|
|
93
|
-
for (const blocked of layoutSyncResults.blockedLayoutDeletions) logger.warn(`[camox] Cannot delete layout "${blocked.layoutId}": still used by ${blocked.pageCount} page${blocked.pageCount === 1 ? "" : "s"}. Reassign or delete those pages first.`, { timestamp: true });
|
|
94
|
-
if (layoutSyncResults.deletedDefinitionTypes.length > 0) {
|
|
95
|
-
const blockList = layoutSyncResults.deletedDefinitionTypes.map((t) => `"${t}"`).join(", ");
|
|
96
|
-
logger.info(`[camox] Removed ${layoutSyncResults.deletedDefinitionTypes.length} layoutOnly block definition${layoutSyncResults.deletedDefinitionTypes.length === 1 ? "" : "s"} (no layout uses ${layoutSyncResults.deletedDefinitionTypes.length === 1 ? "it" : "them"} anymore): ${blockList}`, { timestamp: true });
|
|
58
|
+
if (result.draftCreated) logger.info("[camox] Created your development draft", { timestamp: true });
|
|
59
|
+
logger.info(`[camox] Synced ${counted(result.blocks.count, "block definition")}`, { timestamp: true });
|
|
60
|
+
const { deletedDefinitionTypes } = result.blocks;
|
|
61
|
+
if (deletedDefinitionTypes.length > 0) logger.info(`[camox] Removed ${counted(deletedDefinitionTypes.length, "block definition")} no longer in code: ${quoted(deletedDefinitionTypes)}. Their blocks are kept and render nothing until the definition comes back.`, { timestamp: true });
|
|
62
|
+
logger.info(`[camox] Synced ${result.collections.count} collection definitions`, { timestamp: true });
|
|
63
|
+
for (const id of result.collections.retired) logger.warn(`[camox] Removed collection "${id}"; its records are kept and hidden`, { timestamp: true });
|
|
64
|
+
const layoutSyncResults = result.layouts;
|
|
65
|
+
if (layoutSyncResults) {
|
|
66
|
+
logger.info(`[camox] Synced ${counted(layoutSyncResults.count, "layout")} to Camox API`, { timestamp: true });
|
|
67
|
+
for (const layout of layoutSyncResults.layouts) {
|
|
68
|
+
const { layoutId, createdBlockTypes, removedBlockTypes, skippedOrphanTypes } = layout;
|
|
69
|
+
if (layout.wasExisting && createdBlockTypes.length > 0) logger.info(`[camox] Added ${counted(createdBlockTypes.length, "block")} to existing layout "${layoutId}": ${quoted(createdBlockTypes)}`, { timestamp: true });
|
|
70
|
+
if (removedBlockTypes.length > 0) logger.info(`[camox] Removed ${counted(removedBlockTypes.length, "layoutOnly block")} from layout "${layoutId}": ${quoted(removedBlockTypes)}`, { timestamp: true });
|
|
71
|
+
if (skippedOrphanTypes.length > 0) logger.info(`[camox] Layout "${layoutId}" has ${counted(skippedOrphanTypes.length, "block")} still in DB but removed from code: ${quoted(skippedOrphanTypes)} (kept because not layoutOnly)`, { timestamp: true });
|
|
97
72
|
}
|
|
73
|
+
for (const layoutId of layoutSyncResults.removedLayoutIds) logger.info(`[camox] Removed layout "${layoutId}"; its pages are kept and listed as needing a layout`, { timestamp: true });
|
|
74
|
+
const unused = layoutSyncResults.deletedDefinitionTypes;
|
|
75
|
+
if (unused.length > 0) logger.info(`[camox] Removed ${counted(unused.length, "layoutOnly block definition")} (no layout uses ${unused.length === 1 ? "it" : "them"} anymore): ${quoted(unused)}`, { timestamp: true });
|
|
98
76
|
}
|
|
99
|
-
const
|
|
100
|
-
if (
|
|
101
|
-
|
|
102
|
-
projectSlug,
|
|
103
|
-
deployToken,
|
|
104
|
-
layoutId: initialPage.layoutId,
|
|
105
|
-
blocks: initialPage.blocks
|
|
106
|
-
});
|
|
107
|
-
if (result.created) if (initialPage.hasInitialBlocks) logger.info(`[camox] Initialized content: homepage with ${result.blockCount} block${result.blockCount === 1 ? "" : "s"}`, { timestamp: true });
|
|
77
|
+
const { homepage } = definitionSet;
|
|
78
|
+
if (homepage && result.homepage?.created) {
|
|
79
|
+
if (homepage.hasInitialBlocks) logger.info(`[camox] Initialized content: homepage with ${counted(result.homepage.blockCount, "block")}`, { timestamp: true });
|
|
108
80
|
else {
|
|
109
81
|
logger.info("[camox] Created empty homepage (using first layout)", { timestamp: true });
|
|
110
82
|
logger.info("[camox] Tip: add blocks.initial to your layout to pre-populate pages with content", { timestamp: true });
|
|
111
83
|
}
|
|
112
|
-
} catch (error) {
|
|
113
|
-
throwIfSyncAuthError(error);
|
|
114
|
-
throw error;
|
|
115
84
|
}
|
|
116
85
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
const CAMOX_APP_PATH = "./src/camox/app.ts";
|
|
86
|
+
const VIRTUAL_CAMOX_APP = "virtual:camox/app";
|
|
87
|
+
const RESOLVED_VIRTUAL_CAMOX_APP = "\0virtual:camox/app";
|
|
121
88
|
/**
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
* frameworks configure the SSR environment as non-runnable).
|
|
89
|
+
* The dev server's Node `ssr` environment, which runs alongside the Worker's own environment:
|
|
90
|
+
* the Cloudflare plugin runs the Worker in workerd, where the dev server can't import modules.
|
|
125
91
|
*/
|
|
126
|
-
|
|
92
|
+
function getNodeEnvironment(server) {
|
|
127
93
|
const ssrEnv = server.environments.ssr;
|
|
128
|
-
if (ssrEnv
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
|
|
94
|
+
if (!ssrEnv || !isRunnableDevEnvironment(ssrEnv)) throw new Error("[camox] The dev server has no Node ssr environment to load the app in.");
|
|
95
|
+
return ssrEnv;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The app's current Definition Set, evaluated afresh in the dev server's Node `ssr` environment.
|
|
99
|
+
*/
|
|
100
|
+
async function loadDefinitionSet(server) {
|
|
101
|
+
const nodeEnvironment = getNodeEnvironment(server);
|
|
102
|
+
const appModule = nodeEnvironment.moduleGraph.getModuleById(RESOLVED_VIRTUAL_CAMOX_APP);
|
|
103
|
+
if (appModule) nodeEnvironment.moduleGraph.invalidateModule(appModule);
|
|
104
|
+
nodeEnvironment.runner.evaluatedModules.clear();
|
|
105
|
+
const { camoxApp } = await nodeEnvironment.runner.import(VIRTUAL_CAMOX_APP);
|
|
106
|
+
return camoxApp.getDefinitionSet();
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* A Definition Set as a string that is equal for equal sets: object keys are sorted, and only
|
|
110
|
+
* what reaches the API (JSON) counts.
|
|
111
|
+
*/
|
|
112
|
+
function serializeDefinitionSet(definitionSet) {
|
|
113
|
+
return JSON.stringify(definitionSet, (_key, value) => value && typeof value === "object" && !Array.isArray(value) ? Object.fromEntries(Object.keys(value).sort().map((key) => [key, value[key]])) : value);
|
|
114
|
+
}
|
|
115
|
+
/** Whether the app, as the `ssr` environment last loaded it, imports `file`, even indirectly. */
|
|
116
|
+
function isAppDependency(server, file) {
|
|
117
|
+
const { moduleGraph } = getNodeEnvironment(server);
|
|
118
|
+
const pending = [...moduleGraph.getModulesByFile(file) ?? []];
|
|
119
|
+
const seen = new Set(pending);
|
|
120
|
+
for (let module = pending.pop(); module; module = pending.pop()) {
|
|
121
|
+
if (module.id === RESOLVED_VIRTUAL_CAMOX_APP) return true;
|
|
122
|
+
for (const importer of module.importers) {
|
|
123
|
+
if (seen.has(importer)) continue;
|
|
124
|
+
seen.add(importer);
|
|
125
|
+
pending.push(importer);
|
|
126
|
+
}
|
|
141
127
|
}
|
|
128
|
+
return false;
|
|
142
129
|
}
|
|
130
|
+
/** Whether a file is a script module, which the app's globs may pick up when it appears. */
|
|
131
|
+
function isScriptFile(file) {
|
|
132
|
+
return /\.[cm]?[jt]sx?$/.test(file) && !file.endsWith(".d.ts");
|
|
133
|
+
}
|
|
134
|
+
/** Whether a project's Live has no pages, as on a fresh database. */
|
|
135
|
+
async function liveHasNoPages(apiUrl, projectUuid) {
|
|
136
|
+
const { pages } = await createServerApiClient(apiUrl).pages.listBySlug({ projectUuid });
|
|
137
|
+
return pages.length === 0;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Sync the app's whole Definition Set to the development draft now, then again whenever a module
|
|
141
|
+
* the app depends on changes (debounced), skipping a sync when the set equals the last one sent
|
|
142
|
+
* (ADR 0006). Resolves once the initial sync settles: `synced` if definitions reached the API,
|
|
143
|
+
* and `releasedToLive` if it first released them to an empty Live (`releaseToEmptyLive`).
|
|
144
|
+
*/
|
|
143
145
|
async function syncDefinitions(server, options) {
|
|
144
|
-
const {
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const
|
|
152
|
-
if (
|
|
153
|
-
|
|
154
|
-
|
|
146
|
+
const { projectUuid, apiUrl, autoCreate, authToken, deployToken, releaseToEmptyLive } = options;
|
|
147
|
+
const logger = server.config.logger;
|
|
148
|
+
/** What the development draft last received, so an unchanged set isn't sent again. */
|
|
149
|
+
let lastSynced;
|
|
150
|
+
let releasedToLive = false;
|
|
151
|
+
async function sync({ initial = false } = {}) {
|
|
152
|
+
const definitionSet = await loadDefinitionSet(server);
|
|
153
|
+
const serialized = serializeDefinitionSet(definitionSet);
|
|
154
|
+
if (serialized === lastSynced) return;
|
|
155
|
+
if (initial && releaseToEmptyLive && await liveHasNoPages(apiUrl, projectUuid)) {
|
|
156
|
+
logger.info("[camox] Live is empty: releasing your definitions to it", { timestamp: true });
|
|
157
|
+
await syncDefinitionsToApi({
|
|
158
|
+
definitionSet,
|
|
159
|
+
projectUuid,
|
|
160
|
+
apiUrl,
|
|
161
|
+
autoCreate: false,
|
|
162
|
+
deployToken: releaseToEmptyLive,
|
|
163
|
+
logger
|
|
164
|
+
});
|
|
165
|
+
releasedToLive = true;
|
|
155
166
|
}
|
|
156
167
|
await syncDefinitionsToApi({
|
|
157
|
-
|
|
158
|
-
|
|
168
|
+
definitionSet,
|
|
169
|
+
projectUuid,
|
|
159
170
|
apiUrl,
|
|
160
|
-
environmentName,
|
|
161
171
|
autoCreate,
|
|
162
172
|
authToken,
|
|
163
173
|
deployToken,
|
|
164
|
-
logger
|
|
174
|
+
logger
|
|
165
175
|
});
|
|
176
|
+
lastSynced = serialized;
|
|
166
177
|
}
|
|
167
|
-
|
|
168
|
-
const relativePath = "./" + path.relative(server.config.root, filePath);
|
|
169
|
-
const moduleNode = server.moduleGraph.getModuleById(relativePath);
|
|
170
|
-
if (moduleNode) server.moduleGraph.invalidateModule(moduleNode);
|
|
171
|
-
const blockModule = await ssrLoadModule(server, relativePath);
|
|
172
|
-
if (!blockModule.block) {
|
|
173
|
-
server.config.logger.warn(`[camox] No block export found in ${relativePath}`, { timestamp: true });
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
const block = blockModule.block;
|
|
177
|
-
if (block._internal.layoutOnly) return;
|
|
178
|
-
let result;
|
|
179
|
-
try {
|
|
180
|
-
result = await client.blockDefinitions.upsert({
|
|
181
|
-
projectSlug,
|
|
182
|
-
deployToken,
|
|
183
|
-
blockId: block._internal.id,
|
|
184
|
-
title: block._internal.title,
|
|
185
|
-
description: block._internal.description,
|
|
186
|
-
contentSchema: block._internal.contentSchema,
|
|
187
|
-
settingsSchema: block._internal.settingsSchema,
|
|
188
|
-
defaultContent: block._internal.getInitialContent(),
|
|
189
|
-
defaultSettings: block._internal.getInitialSettings(),
|
|
190
|
-
layoutOnly: block._internal.layoutOnly || void 0,
|
|
191
|
-
synced: block._internal.synced
|
|
192
|
-
});
|
|
193
|
-
} catch (error) {
|
|
194
|
-
throwIfSyncAuthError(error);
|
|
195
|
-
throw error;
|
|
196
|
-
}
|
|
197
|
-
server.config.logger.info(`[camox] ${result.action === "created" ? "Created" : "Updated"} block definition "${block._internal.id}"`, { timestamp: true });
|
|
198
|
-
}
|
|
199
|
-
async function deleteBlock(filePath) {
|
|
200
|
-
const blockId = getBlockIdFromFilePath(filePath);
|
|
201
|
-
let result;
|
|
202
|
-
try {
|
|
203
|
-
result = await client.blockDefinitions.delete({
|
|
204
|
-
projectSlug,
|
|
205
|
-
deployToken,
|
|
206
|
-
blockId
|
|
207
|
-
});
|
|
208
|
-
} catch (error) {
|
|
209
|
-
throwIfSyncAuthError(error);
|
|
210
|
-
throw error;
|
|
211
|
-
}
|
|
212
|
-
if (result.deleted) server.config.logger.info(`[camox] Deleted block definition "${blockId}"`, { timestamp: true });
|
|
213
|
-
}
|
|
178
|
+
let synced = false;
|
|
214
179
|
try {
|
|
215
|
-
await
|
|
180
|
+
await sync({ initial: true });
|
|
181
|
+
synced = true;
|
|
216
182
|
} catch (error) {
|
|
217
|
-
|
|
183
|
+
logger.error(`[camox] Failed to sync block definitions: ${String(error)}`, { timestamp: true });
|
|
218
184
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
if (!isBlockFile(filePath)) return;
|
|
228
|
-
const existingTimer = debounceTimers.get(filePath);
|
|
229
|
-
if (existingTimer) clearTimeout(existingTimer);
|
|
230
|
-
debounceTimers.set(filePath, setTimeout(async () => {
|
|
231
|
-
debounceTimers.delete(filePath);
|
|
232
|
-
try {
|
|
233
|
-
await upsertBlock(filePath);
|
|
234
|
-
} catch (error) {
|
|
235
|
-
server.config.logger.error(`[camox] Failed to sync block: ${String(error)}`, { timestamp: true });
|
|
236
|
-
}
|
|
237
|
-
}, SYNC_DEBOUNCE_DELAY_MS));
|
|
238
|
-
};
|
|
239
|
-
const handleBlockFileDelete = (filePath) => {
|
|
240
|
-
if (!isBlockFile(filePath)) return;
|
|
241
|
-
const existingTimer = debounceTimers.get(filePath);
|
|
242
|
-
if (existingTimer) {
|
|
243
|
-
clearTimeout(existingTimer);
|
|
244
|
-
debounceTimers.delete(filePath);
|
|
245
|
-
}
|
|
246
|
-
setTimeout(async () => {
|
|
247
|
-
try {
|
|
248
|
-
await deleteBlock(filePath);
|
|
249
|
-
} catch (error) {
|
|
250
|
-
server.config.logger.error(`[camox] Failed to delete block: ${String(error)}`, { timestamp: true });
|
|
251
|
-
}
|
|
185
|
+
let running = Promise.resolve();
|
|
186
|
+
let timer;
|
|
187
|
+
const scheduleSync = () => {
|
|
188
|
+
clearTimeout(timer);
|
|
189
|
+
timer = setTimeout(() => {
|
|
190
|
+
running = running.then(() => sync().catch((error) => {
|
|
191
|
+
logger.error(`[camox] Failed to sync block definitions: ${String(error)}`, { timestamp: true });
|
|
192
|
+
}));
|
|
252
193
|
}, SYNC_DEBOUNCE_DELAY_MS);
|
|
253
194
|
};
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
server.config.logger.error(`[camox] Failed to sync layouts: ${String(error)}`, { timestamp: true });
|
|
267
|
-
}
|
|
268
|
-
}, SYNC_DEBOUNCE_DELAY_MS);
|
|
195
|
+
server.watcher.on("change", (file) => {
|
|
196
|
+
if (isAppDependency(server, file)) scheduleSync();
|
|
197
|
+
});
|
|
198
|
+
server.watcher.on("add", (file) => {
|
|
199
|
+
if (isScriptFile(file)) scheduleSync();
|
|
200
|
+
});
|
|
201
|
+
server.watcher.on("unlink", (file) => {
|
|
202
|
+
if (isScriptFile(file) || isAppDependency(server, file)) scheduleSync();
|
|
203
|
+
});
|
|
204
|
+
return {
|
|
205
|
+
synced,
|
|
206
|
+
releasedToLive
|
|
269
207
|
};
|
|
270
|
-
server.watcher.on("change", handleBlockFileUpsert);
|
|
271
|
-
server.watcher.on("change", handleLayoutFileChange);
|
|
272
|
-
server.watcher.on("add", handleBlockFileUpsert);
|
|
273
|
-
server.watcher.on("add", handleLayoutFileChange);
|
|
274
|
-
server.watcher.on("unlink", handleBlockFileDelete);
|
|
275
|
-
server.watcher.on("unlink", handleLayoutFileChange);
|
|
276
208
|
}
|
|
277
209
|
|
|
278
210
|
//#endregion
|
|
279
|
-
export { syncDefinitions, syncDefinitionsToApi };
|
|
211
|
+
export { VIRTUAL_CAMOX_APP, syncDefinitions, syncDefinitionsToApi };
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { authPageStyles } from "../../lib/auth-page-styles.js";
|
|
1
2
|
import { verifyOneTimeToken, writeAuthTokenForUrl } from "./auth.js";
|
|
2
3
|
import { randomBytes } from "node:crypto";
|
|
3
4
|
|
|
4
5
|
//#region src/features/vite/devAuthentication.ts
|
|
5
6
|
const CALLBACK_PATH = "/__camox/auth/callback";
|
|
6
7
|
const READY_PATH = "/__camox/auth/ready";
|
|
7
|
-
const AUTH_REQUEST_TTL_MS =
|
|
8
|
+
const AUTH_REQUEST_TTL_MS = 6e5;
|
|
8
9
|
function normalizeUrl(url) {
|
|
9
10
|
return url.replace(/\/+$/, "");
|
|
10
11
|
}
|
|
@@ -57,17 +58,10 @@ function sendRestartingPage(res, returnPath) {
|
|
|
57
58
|
<meta charset="utf-8" />
|
|
58
59
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
59
60
|
<title>Connecting to Camox…</title>
|
|
60
|
-
<style>
|
|
61
|
-
:root { color-scheme: dark; font-family: Inter, ui-sans-serif, system-ui, sans-serif; }
|
|
62
|
-
body { align-items: center; background: #09090b; color: #fafafa; display: flex; justify-content: center; margin: 0; min-height: 100vh; }
|
|
63
|
-
main { align-items: center; display: flex; flex-direction: column; gap: 16px; text-align: center; }
|
|
64
|
-
.spinner { animation: spin 800ms linear infinite; border: 2px solid #3f3f46; border-radius: 999px; border-top-color: #fafafa; height: 24px; width: 24px; }
|
|
65
|
-
p { color: #a1a1aa; margin: 0; }
|
|
66
|
-
@keyframes spin { to { transform: rotate(360deg); } }
|
|
67
|
-
</style>
|
|
61
|
+
<style>${authPageStyles}</style>
|
|
68
62
|
</head>
|
|
69
63
|
<body>
|
|
70
|
-
<main><div class="spinner"></div><p>Starting your Camox site…</p></main>
|
|
64
|
+
<main class="camox-auth-page" role="status"><div class="camox-auth-spinner" aria-hidden="true"></div><p>Starting your Camox site…</p></main>
|
|
71
65
|
<script>
|
|
72
66
|
const returnPath = ${serializedReturnPath};
|
|
73
67
|
async function waitUntilReady() {
|
|
@@ -144,12 +138,6 @@ function installDevAuthenticationMiddleware(server, options) {
|
|
|
144
138
|
}
|
|
145
139
|
redirect(res, authorizationUrl.toString());
|
|
146
140
|
});
|
|
147
|
-
const authenticationLayer = server.middlewares.stack.at(-1);
|
|
148
|
-
const nitroMiddlewareIndex = server.middlewares.stack.findIndex((layer) => typeof layer.handle === "function" && layer.handle.name === "nitroDevMiddlewarePre");
|
|
149
|
-
if (authenticationLayer && nitroMiddlewareIndex >= 0) {
|
|
150
|
-
server.middlewares.stack.pop();
|
|
151
|
-
server.middlewares.stack.splice(nitroMiddlewareIndex, 0, authenticationLayer);
|
|
152
|
-
}
|
|
153
141
|
}
|
|
154
142
|
async function handleAuthenticationCallback(req, res, server, options, pendingAuthentications) {
|
|
155
143
|
const requestUrl = new URL(req.url ?? "/", "http://localhost");
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { createPreviewSignInUrl, isLoopbackUrl } from "@camox/cli/auth";
|
|
2
|
+
import childProcess from "node:child_process";
|
|
3
|
+
import { open } from "node:fs/promises";
|
|
4
|
+
import { setTimeout } from "node:timers/promises";
|
|
5
|
+
|
|
6
|
+
//#region src/features/vite/devSignIn.ts
|
|
7
|
+
const openedKey = Symbol.for("camox.devSignIn.opened");
|
|
8
|
+
const processState = globalThis;
|
|
9
|
+
const opened = processState[openedKey] ??= /* @__PURE__ */ new Set();
|
|
10
|
+
function openBrowser(url, onError) {
|
|
11
|
+
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "rundll32.exe" : "xdg-open";
|
|
12
|
+
const args = process.platform === "win32" ? ["url.dll,FileProtocolHandler", url] : [url];
|
|
13
|
+
try {
|
|
14
|
+
const child = childProcess.spawn(command, args, {
|
|
15
|
+
stdio: "ignore",
|
|
16
|
+
detached: true
|
|
17
|
+
});
|
|
18
|
+
child.once("error", onError);
|
|
19
|
+
child.once("exit", (code) => {
|
|
20
|
+
if (code !== 0) onError();
|
|
21
|
+
});
|
|
22
|
+
child.unref();
|
|
23
|
+
} catch {
|
|
24
|
+
onError();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** Mint only after Vite has resolved its actual port, including port fallback. */
|
|
28
|
+
function installDevSignInLink(server, options) {
|
|
29
|
+
const controller = new AbortController();
|
|
30
|
+
server.httpServer?.once("close", () => controller.abort());
|
|
31
|
+
const printUrls = server.printUrls.bind(server);
|
|
32
|
+
let started = false;
|
|
33
|
+
server.printUrls = () => {
|
|
34
|
+
printUrls();
|
|
35
|
+
if (started) return;
|
|
36
|
+
const urls = server.resolvedUrls;
|
|
37
|
+
const destination = [...urls?.local ?? [], ...urls?.network ?? []].find((url) => isLoopbackUrl(new URL(url)));
|
|
38
|
+
if (!destination) return;
|
|
39
|
+
started = true;
|
|
40
|
+
printSignInLink(destination);
|
|
41
|
+
};
|
|
42
|
+
async function printSignInLink(destination) {
|
|
43
|
+
const signal = AbortSignal.any([controller.signal, AbortSignal.timeout(3e4)]);
|
|
44
|
+
while (!signal.aborted) try {
|
|
45
|
+
const url = await createPreviewSignInUrl(destination, {
|
|
46
|
+
projectUuid: options.projectUuid,
|
|
47
|
+
apiUrl: options.apiUrl
|
|
48
|
+
}, options.authToken, signal);
|
|
49
|
+
if (signal.aborted) return;
|
|
50
|
+
server.config.logger.info(` ➜ Camox sign in (single-use, expires in 3 minutes; do not share): ${url}`);
|
|
51
|
+
if (options.open) await openSignInLink(url);
|
|
52
|
+
return;
|
|
53
|
+
} catch {
|
|
54
|
+
try {
|
|
55
|
+
await setTimeout(1e3, void 0, { signal });
|
|
56
|
+
} catch {
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (controller.signal.aborted) return;
|
|
61
|
+
server.config.logger.warn("Camox sign-in link unavailable. Use the normal local URL to sign in, or run camox preview for a fresh link.");
|
|
62
|
+
}
|
|
63
|
+
async function openSignInLink(url) {
|
|
64
|
+
let warned = false;
|
|
65
|
+
const warn = () => {
|
|
66
|
+
if (warned || controller.signal.aborted) return;
|
|
67
|
+
warned = true;
|
|
68
|
+
server.config.logger.warn("Camox could not open your browser. Use the sign-in link printed above.");
|
|
69
|
+
};
|
|
70
|
+
try {
|
|
71
|
+
if (options.openOnceFile) await (await open(options.openOnceFile, "wx", 384)).close();
|
|
72
|
+
else {
|
|
73
|
+
const key = JSON.stringify([server.config.root, options.projectUuid]);
|
|
74
|
+
if (opened.has(key)) return;
|
|
75
|
+
opened.add(key);
|
|
76
|
+
}
|
|
77
|
+
if (controller.signal.aborted) return;
|
|
78
|
+
openBrowser(url, warn);
|
|
79
|
+
} catch (error) {
|
|
80
|
+
if (error.code === "EEXIST") return;
|
|
81
|
+
warn();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
//#endregion
|
|
87
|
+
export { installDevSignInLink };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { iconCollectionIds, loadIconCollection } from "@camox/api-contract";
|
|
2
1
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
3
2
|
import { resolve } from "node:path";
|
|
3
|
+
import { iconCollectionIds, loadIconCollection } from "@camox/api-contract/icon-catalog";
|
|
4
4
|
|
|
5
5
|
//#region src/features/vite/iconGeneration.ts
|
|
6
6
|
async function generateIconTypes(root, prefix) {
|
|
@@ -37,6 +37,16 @@ export const Layout = createLayout(${JSON.stringify(id)})({
|
|
|
37
37
|
}
|
|
38
38
|
writeIfChanged(resolve(appRoot, "src/camox/layouts.gen.d.ts"), `// Generated by Camox.\nimport "camox/createLayout";\ndeclare module "camox/createLayout" {\n interface LayoutFileRoutes ${declarations.length ? `{\n${declarations.join("\n")}\n }` : "{}"}\n}\n`);
|
|
39
39
|
}
|
|
40
|
+
/** Regenerate layout files whenever a layout file is added, changed or deleted. */
|
|
41
|
+
function watchLayoutFiles(server, appRoot) {
|
|
42
|
+
for (const event of [
|
|
43
|
+
"add",
|
|
44
|
+
"change",
|
|
45
|
+
"unlink"
|
|
46
|
+
]) server.watcher.on(event, (path) => {
|
|
47
|
+
if (path.startsWith(resolve(appRoot, "src/layouts") + "/")) generateLayoutFiles(appRoot);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
40
50
|
|
|
41
51
|
//#endregion
|
|
42
|
-
export { generateLayoutFiles };
|
|
52
|
+
export { generateLayoutFiles, watchLayoutFiles };
|