camox 0.0.0 → 0.1.2-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +110 -0
- package/dist/components/AuthGate.d.ts +7 -0
- package/dist/components/AuthGate.d.ts.map +1 -0
- package/dist/core/components/AddBlockControlBar.d.ts +9 -0
- package/dist/core/components/AddBlockControlBar.d.ts.map +1 -0
- package/dist/core/components/AddBlockControlBar.js +65 -0
- package/dist/core/components/lexical/InlineContentEditable.d.ts +7 -0
- package/dist/core/components/lexical/InlineContentEditable.d.ts.map +1 -0
- package/dist/core/components/lexical/InlineContentEditable.js +40 -0
- package/dist/core/components/lexical/InlineLexicalEditor.d.ts +12 -0
- package/dist/core/components/lexical/InlineLexicalEditor.d.ts.map +1 -0
- package/dist/core/components/lexical/InlineLexicalEditor.js +133 -0
- package/dist/core/components/lexical/InlineParagraphNode.d.ts +10 -0
- package/dist/core/components/lexical/InlineParagraphNode.d.ts.map +1 -0
- package/dist/core/components/lexical/InlineParagraphNode.js +34 -0
- package/dist/core/components/lexical/SelectionBroadcaster.d.ts +6 -0
- package/dist/core/components/lexical/SelectionBroadcaster.d.ts.map +1 -0
- package/dist/core/components/lexical/SelectionBroadcaster.js +62 -0
- package/dist/core/components/lexical/SidebarLexicalEditor.d.ts +9 -0
- package/dist/core/components/lexical/SidebarLexicalEditor.d.ts.map +1 -0
- package/dist/core/components/lexical/editorConfig.d.ts +4 -0
- package/dist/core/components/lexical/editorConfig.d.ts.map +1 -0
- package/dist/core/components/lexical/editorConfig.js +24 -0
- package/dist/core/createApp.d.ts +373 -0
- package/dist/core/createApp.d.ts.map +1 -0
- package/dist/core/createApp.js +40 -0
- package/dist/core/createBlock.d.ts +947 -0
- package/dist/core/createBlock.d.ts.map +1 -0
- package/dist/core/createBlock.js +873 -0
- package/dist/core/createLayout.d.ts +78 -0
- package/dist/core/createLayout.d.ts.map +1 -0
- package/dist/core/createLayout.js +73 -0
- package/dist/core/hooks/useFieldSelection.d.ts +11 -0
- package/dist/core/hooks/useFieldSelection.d.ts.map +1 -0
- package/dist/core/hooks/useFieldSelection.js +25 -0
- package/dist/core/hooks/useIsEditable.d.ts +2 -0
- package/dist/core/hooks/useIsEditable.d.ts.map +1 -0
- package/dist/core/hooks/useIsEditable.js +12 -0
- package/dist/core/hooks/useOverlayMessage.d.ts +10 -0
- package/dist/core/hooks/useOverlayMessage.d.ts.map +1 -0
- package/dist/core/hooks/useOverlayMessage.js +37 -0
- package/dist/core/lib/contentType.d.ts +165 -0
- package/dist/core/lib/contentType.d.ts.map +1 -0
- package/dist/core/lib/contentType.js +148 -0
- package/dist/core/lib/fieldTypes.d.ts +85 -0
- package/dist/core/lib/fieldTypes.d.ts.map +1 -0
- package/dist/core/lib/lexicalReact.d.ts +3 -0
- package/dist/core/lib/lexicalReact.d.ts.map +1 -0
- package/dist/core/lib/lexicalReact.js +24 -0
- package/dist/core/lib/lexicalState.d.ts +10 -0
- package/dist/core/lib/lexicalState.d.ts.map +1 -0
- package/dist/core/lib/lexicalState.js +38 -0
- package/dist/core/lib/modifierFormats.d.ts +9 -0
- package/dist/core/lib/modifierFormats.d.ts.map +1 -0
- package/dist/core/lib/modifierFormats.js +8 -0
- package/dist/core/lib/modifiers.d.ts +12 -0
- package/dist/core/lib/modifiers.d.ts.map +1 -0
- package/dist/core/lib/modifiers.js +27 -0
- package/dist/features/content/CamoxContent.d.ts +2 -0
- package/dist/features/content/CamoxContent.d.ts.map +1 -0
- package/dist/features/content/CamoxContent.js +100 -0
- package/dist/features/content/components/AssetCard.d.ts +10 -0
- package/dist/features/content/components/AssetCard.d.ts.map +1 -0
- package/dist/features/content/components/AssetCard.js +41 -0
- package/dist/features/content/components/AssetCardSkeleton.d.ts +2 -0
- package/dist/features/content/components/AssetCardSkeleton.d.ts.map +1 -0
- package/dist/features/content/components/AssetCardSkeleton.js +11 -0
- package/dist/features/content/components/ContentSidebar.d.ts +2 -0
- package/dist/features/content/components/ContentSidebar.d.ts.map +1 -0
- package/dist/features/content/components/ContentSidebar.js +15 -0
- package/dist/features/content/components/UploadDropZone.d.ts +9 -0
- package/dist/features/content/components/UploadDropZone.d.ts.map +1 -0
- package/dist/features/content/components/UploadDropZone.js +51 -0
- package/dist/features/content/components/UploadProgressDrawer.d.ts +11 -0
- package/dist/features/content/components/UploadProgressDrawer.d.ts.map +1 -0
- package/dist/features/content/components/UploadProgressDrawer.js +72 -0
- package/dist/features/preview/CamoxPreview.d.ts +124 -0
- package/dist/features/preview/CamoxPreview.d.ts.map +1 -0
- package/dist/features/preview/CamoxPreview.js +253 -0
- package/dist/features/preview/components/AddBlockSheet.d.ts +3 -0
- package/dist/features/preview/components/AddBlockSheet.d.ts.map +1 -0
- package/dist/features/preview/components/AddBlockSheet.js +121 -0
- package/dist/features/preview/components/AgentChatSheet.d.ts +3 -0
- package/dist/features/preview/components/AgentChatSheet.d.ts.map +1 -0
- package/dist/features/preview/components/AgentChatSheet.js +24 -0
- package/dist/features/preview/components/AssetFieldEditor.d.ts +18 -0
- package/dist/features/preview/components/AssetFieldEditor.d.ts.map +1 -0
- package/dist/features/preview/components/AssetFieldEditor.js +139 -0
- package/dist/features/preview/components/AssetLightbox.d.ts +9 -0
- package/dist/features/preview/components/AssetLightbox.d.ts.map +1 -0
- package/dist/features/preview/components/AssetLightbox.js +421 -0
- package/dist/features/preview/components/AssetPickerGrid.d.ts +11 -0
- package/dist/features/preview/components/AssetPickerGrid.d.ts.map +1 -0
- package/dist/features/preview/components/AssetPickerGrid.js +92 -0
- package/dist/features/preview/components/BlockActionsPopover.d.ts +15 -0
- package/dist/features/preview/components/BlockActionsPopover.d.ts.map +1 -0
- package/dist/features/preview/components/BlockActionsPopover.js +506 -0
- package/dist/features/preview/components/CreatePageSheet.d.ts +3 -0
- package/dist/features/preview/components/CreatePageSheet.d.ts.map +1 -0
- package/dist/features/preview/components/CreatePageSheet.js +159 -0
- package/dist/features/preview/components/DebouncedFieldEditor.d.ts +10 -0
- package/dist/features/preview/components/DebouncedFieldEditor.d.ts.map +1 -0
- package/dist/features/preview/components/DebouncedFieldEditor.js +51 -0
- package/dist/features/preview/components/EditPageSheet.d.ts +3 -0
- package/dist/features/preview/components/EditPageSheet.d.ts.map +1 -0
- package/dist/features/preview/components/EditPageSheet.js +352 -0
- package/dist/features/preview/components/ItemFieldsEditor.d.ts +29 -0
- package/dist/features/preview/components/ItemFieldsEditor.d.ts.map +1 -0
- package/dist/features/preview/components/ItemFieldsEditor.js +308 -0
- package/dist/features/preview/components/LinkFieldEditor.d.ts +8 -0
- package/dist/features/preview/components/LinkFieldEditor.d.ts.map +1 -0
- package/dist/features/preview/components/LinkFieldEditor.js +190 -0
- package/dist/features/preview/components/MultipleAssetFieldEditor.d.ts +10 -0
- package/dist/features/preview/components/MultipleAssetFieldEditor.d.ts.map +1 -0
- package/dist/features/preview/components/MultipleAssetFieldEditor.js +232 -0
- package/dist/features/preview/components/OverlayTracker.d.ts +6 -0
- package/dist/features/preview/components/OverlayTracker.d.ts.map +1 -0
- package/dist/features/preview/components/OverlayTracker.js +41 -0
- package/dist/features/preview/components/Overlays.d.ts +6 -0
- package/dist/features/preview/components/Overlays.d.ts.map +1 -0
- package/dist/features/preview/components/Overlays.js +58 -0
- package/dist/features/preview/components/PageContentSheet.d.ts +3 -0
- package/dist/features/preview/components/PageContentSheet.d.ts.map +1 -0
- package/dist/features/preview/components/PageContentSheet.js +492 -0
- package/dist/features/preview/components/PageLocationFieldset.d.ts +14 -0
- package/dist/features/preview/components/PageLocationFieldset.d.ts.map +1 -0
- package/dist/features/preview/components/PageLocationFieldset.js +77 -0
- package/dist/features/preview/components/PagePicker.d.ts +3 -0
- package/dist/features/preview/components/PagePicker.d.ts.map +1 -0
- package/dist/features/preview/components/PagePicker.js +185 -0
- package/dist/features/preview/components/PageTree.d.ts +3 -0
- package/dist/features/preview/components/PageTree.d.ts.map +1 -0
- package/dist/features/preview/components/PageTree.js +410 -0
- package/dist/features/preview/components/PeekedBlock.d.ts +6 -0
- package/dist/features/preview/components/PeekedBlock.d.ts.map +1 -0
- package/dist/features/preview/components/PeekedBlock.js +95 -0
- package/dist/features/preview/components/PreviewPanel.d.ts +12 -0
- package/dist/features/preview/components/PreviewPanel.d.ts.map +1 -0
- package/dist/features/preview/components/PreviewPanel.js +192 -0
- package/dist/features/preview/components/PreviewSideSheet.d.ts +13 -0
- package/dist/features/preview/components/PreviewSideSheet.d.ts.map +1 -0
- package/dist/features/preview/components/PreviewSideSheet.js +28 -0
- package/dist/features/preview/components/PreviewToolbar.d.ts +2 -0
- package/dist/features/preview/components/PreviewToolbar.d.ts.map +1 -0
- package/dist/features/preview/components/PreviewToolbar.js +79 -0
- package/dist/features/preview/components/RepeatableItemsList.d.ts +14 -0
- package/dist/features/preview/components/RepeatableItemsList.d.ts.map +1 -0
- package/dist/features/preview/components/RepeatableItemsList.js +366 -0
- package/dist/features/preview/components/ShikiMarkdown.d.ts +4 -0
- package/dist/features/preview/components/ShikiMarkdown.d.ts.map +1 -0
- package/dist/features/preview/components/ShikiMarkdown.js +37 -0
- package/dist/features/preview/components/TextFormatToolbar.d.ts +2 -0
- package/dist/features/preview/components/TextFormatToolbar.d.ts.map +1 -0
- package/dist/features/preview/components/TextFormatToolbar.js +73 -0
- package/dist/features/preview/components/UnlinkAssetButton.d.ts +9 -0
- package/dist/features/preview/components/UnlinkAssetButton.d.ts.map +1 -0
- package/dist/features/preview/components/UnlinkAssetButton.js +55 -0
- package/dist/features/preview/overlayConstants.d.ts +19 -0
- package/dist/features/preview/overlayConstants.d.ts.map +1 -0
- package/dist/features/preview/overlayConstants.js +21 -0
- package/dist/features/preview/overlayMessages.d.ts +62 -0
- package/dist/features/preview/overlayMessages.d.ts.map +1 -0
- package/dist/features/preview/overlayMessages.js +9 -0
- package/dist/features/preview/previewConstants.d.ts +2 -0
- package/dist/features/preview/previewConstants.d.ts.map +1 -0
- package/dist/features/preview/previewStore.d.ts +116 -0
- package/dist/features/preview/previewStore.d.ts.map +1 -0
- package/dist/features/preview/previewStore.js +321 -0
- package/dist/features/provider/CamoxProvider.d.ts +11 -0
- package/dist/features/provider/CamoxProvider.d.ts.map +1 -0
- package/dist/features/provider/CamoxProvider.js +73 -0
- package/dist/features/provider/actionsStore.d.ts +39 -0
- package/dist/features/provider/actionsStore.d.ts.map +1 -0
- package/dist/features/provider/actionsStore.js +35 -0
- package/dist/features/provider/components/CamoxAppContext.d.ts +371 -0
- package/dist/features/provider/components/CamoxAppContext.d.ts.map +1 -0
- package/dist/features/provider/components/CamoxAppContext.js +17 -0
- package/dist/features/provider/components/CommandPalette.d.ts +3 -0
- package/dist/features/provider/components/CommandPalette.d.ts.map +1 -0
- package/dist/features/provider/components/CommandPalette.js +127 -0
- package/dist/features/provider/useAdminShortcuts.d.ts +5 -0
- package/dist/features/provider/useAdminShortcuts.d.ts.map +1 -0
- package/dist/features/provider/useAdminShortcuts.js +83 -0
- package/dist/features/routes/ogRoute.d.ts +7 -0
- package/dist/features/routes/ogRoute.d.ts.map +1 -0
- package/dist/features/routes/ogRoute.js +19 -0
- package/dist/features/routes/pageRoute.d.ts +135 -0
- package/dist/features/routes/pageRoute.d.ts.map +1 -0
- package/dist/features/routes/pageRoute.js +112 -0
- package/dist/features/studio/CamoxStudio.d.ts +7 -0
- package/dist/features/studio/CamoxStudio.d.ts.map +1 -0
- package/dist/features/studio/CamoxStudio.js +24 -0
- package/dist/features/studio/components/Navbar.d.ts +4 -0
- package/dist/features/studio/components/Navbar.d.ts.map +1 -0
- package/dist/features/studio/components/Navbar.js +95 -0
- package/dist/features/studio/components/ProjectMenu.d.ts +2 -0
- package/dist/features/studio/components/ProjectMenu.d.ts.map +1 -0
- package/dist/features/studio/components/ProjectMenu.js +132 -0
- package/dist/features/studio/components/UserButton.d.ts +2 -0
- package/dist/features/studio/components/UserButton.d.ts.map +1 -0
- package/dist/features/studio/components/UserButton.js +96 -0
- package/dist/features/studio/studioStore.d.ts +17 -0
- package/dist/features/studio/studioStore.d.ts.map +1 -0
- package/dist/features/studio/studioStore.js +44 -0
- package/dist/features/studio/useTheme.d.ts +9 -0
- package/dist/features/studio/useTheme.d.ts.map +1 -0
- package/dist/features/studio/useTheme.js +98 -0
- package/dist/features/vite/appGeneration.d.ts +4 -0
- package/dist/features/vite/appGeneration.d.ts.map +1 -0
- package/dist/features/vite/appGeneration.js +67 -0
- package/dist/features/vite/blockBoilerplate.d.ts +3 -0
- package/dist/features/vite/blockBoilerplate.d.ts.map +1 -0
- package/dist/features/vite/blockBoilerplate.js +59 -0
- package/dist/features/vite/convexSync.d.ts +6 -0
- package/dist/features/vite/convexSync.d.ts.map +1 -0
- package/dist/features/vite/convexSync.js +98 -0
- package/dist/features/vite/definitionsSync.d.ts +11 -0
- package/dist/features/vite/definitionsSync.d.ts.map +1 -0
- package/dist/features/vite/definitionsSync.js +157 -0
- package/dist/features/vite/routeGeneration.d.ts +4 -0
- package/dist/features/vite/routeGeneration.d.ts.map +1 -0
- package/dist/features/vite/routeGeneration.js +194 -0
- package/dist/features/vite/skillGeneration.d.ts +4 -0
- package/dist/features/vite/skillGeneration.d.ts.map +1 -0
- package/dist/features/vite/skillGeneration.js +69 -0
- package/dist/features/vite/utils.d.ts +2 -0
- package/dist/features/vite/utils.d.ts.map +1 -0
- package/dist/features/vite/utils.js +10 -0
- package/dist/features/vite/vite.d.ts +18 -0
- package/dist/features/vite/vite.d.ts.map +1 -0
- package/dist/features/vite/vite.js +77 -0
- package/dist/hooks/use-file-upload.d.ts +22 -0
- package/dist/hooks/use-file-upload.d.ts.map +1 -0
- package/dist/hooks/use-marquee-selection.d.ts +17 -0
- package/dist/hooks/use-marquee-selection.d.ts.map +1 -0
- package/dist/lib/analytics-client.d.ts +3 -0
- package/dist/lib/analytics-client.d.ts.map +1 -0
- package/dist/lib/analytics.d.ts +3 -0
- package/dist/lib/analytics.d.ts.map +1 -0
- package/dist/lib/analytics.js +24 -0
- package/dist/lib/auth.d.ts +3683 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/convex-site.d.ts +3 -0
- package/dist/lib/convex-site.d.ts.map +1 -0
- package/dist/lib/utils.d.ts +40 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/studio.css +2 -0
- package/package.json +123 -10
- package/server/api.d.ts +1 -0
- package/server/api.js +1 -0
- package/server/dataModel.d.ts +1 -0
- package/server/dataModel.js +1 -0
- package/skills/camox-block/SKILL.md +357 -0
- package/skills/camox-layout/SKILL.md +181 -0
- package/index.js +0 -3
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createStore } from "@xstate/store";
|
|
2
|
+
//#region src/features/studio/studioStore.ts
|
|
3
|
+
var studioStore = createStore({
|
|
4
|
+
context: {
|
|
5
|
+
isCommandPaletteOpen: false,
|
|
6
|
+
commandPalettePages: []
|
|
7
|
+
},
|
|
8
|
+
on: {
|
|
9
|
+
openCommandPalette: (context) => {
|
|
10
|
+
return {
|
|
11
|
+
...context,
|
|
12
|
+
isCommandPaletteOpen: true
|
|
13
|
+
};
|
|
14
|
+
},
|
|
15
|
+
closeCommandPalette: (context) => {
|
|
16
|
+
return {
|
|
17
|
+
...context,
|
|
18
|
+
isCommandPaletteOpen: false,
|
|
19
|
+
commandPalettePage: null
|
|
20
|
+
};
|
|
21
|
+
},
|
|
22
|
+
toggleCommandPalette: (context) => {
|
|
23
|
+
return {
|
|
24
|
+
...context,
|
|
25
|
+
isCommandPaletteOpen: !context.isCommandPaletteOpen,
|
|
26
|
+
commandPalettePages: []
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
pushCommandPalettePage: (context, event) => {
|
|
30
|
+
return {
|
|
31
|
+
...context,
|
|
32
|
+
commandPalettePages: [...context.commandPalettePages, event.page]
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
popCommandPalettePage: (context) => {
|
|
36
|
+
return {
|
|
37
|
+
...context,
|
|
38
|
+
commandPalettePages: context.commandPalettePages.slice(0, -1)
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
//#endregion
|
|
44
|
+
export { studioStore };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
type Theme = "dark" | "light" | "system";
|
|
3
|
+
export declare function useTheme(): {
|
|
4
|
+
theme: Theme;
|
|
5
|
+
setTheme: React.Dispatch<React.SetStateAction<Theme>>;
|
|
6
|
+
};
|
|
7
|
+
export declare function useThemeActions(): void;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=useTheme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTheme.d.ts","sourceRoot":"","sources":["../../../src/features/studio/useTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,KAAK,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAazC,wBAAgB,QAAQ;;;EAiDvB;AAED,wBAAgB,eAAe,SAqD9B"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { actionsStore } from "../provider/actionsStore.js";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
//#region src/features/studio/useTheme.ts
|
|
4
|
+
var getThemeIcon = (theme) => {
|
|
5
|
+
switch (theme) {
|
|
6
|
+
case "dark": return "Moon";
|
|
7
|
+
case "light": return "Sun";
|
|
8
|
+
case "system": return "Monitor";
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
function useTheme() {
|
|
12
|
+
const [theme, setTheme] = React.useState(() => {
|
|
13
|
+
if (typeof window !== "undefined") return localStorage.getItem("theme") || "system";
|
|
14
|
+
return "system";
|
|
15
|
+
});
|
|
16
|
+
const applyTheme = (themeToApply) => {
|
|
17
|
+
const root = window.document.documentElement;
|
|
18
|
+
root.classList.remove("light", "dark");
|
|
19
|
+
root.classList.add(themeToApply);
|
|
20
|
+
};
|
|
21
|
+
React.useEffect(() => {
|
|
22
|
+
const root = window.document.documentElement;
|
|
23
|
+
root.classList.remove("light", "dark");
|
|
24
|
+
if (theme === "system") {
|
|
25
|
+
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
26
|
+
const updateSystemTheme = () => {
|
|
27
|
+
applyTheme(mediaQuery.matches ? "dark" : "light");
|
|
28
|
+
};
|
|
29
|
+
updateSystemTheme();
|
|
30
|
+
mediaQuery.addEventListener("change", updateSystemTheme);
|
|
31
|
+
return () => mediaQuery.removeEventListener("change", updateSystemTheme);
|
|
32
|
+
}
|
|
33
|
+
root.classList.add(theme);
|
|
34
|
+
}, [theme]);
|
|
35
|
+
React.useEffect(() => {
|
|
36
|
+
localStorage.setItem("theme", theme);
|
|
37
|
+
}, [theme]);
|
|
38
|
+
return {
|
|
39
|
+
theme,
|
|
40
|
+
setTheme
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function useThemeActions() {
|
|
44
|
+
const { theme, setTheme } = useTheme();
|
|
45
|
+
React.useEffect(() => {
|
|
46
|
+
const pageId = "change-theme";
|
|
47
|
+
const actions = [
|
|
48
|
+
{
|
|
49
|
+
id: pageId,
|
|
50
|
+
label: "Change theme",
|
|
51
|
+
groupLabel: "Studio",
|
|
52
|
+
checkIfAvailable: () => true,
|
|
53
|
+
hasChildren: true,
|
|
54
|
+
execute: () => {},
|
|
55
|
+
icon: getThemeIcon(theme)
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: "switch-to-light-theme",
|
|
59
|
+
parentActionId: pageId,
|
|
60
|
+
label: "Switch to light theme",
|
|
61
|
+
groupLabel: "Studio",
|
|
62
|
+
checkIfAvailable: () => theme !== "light",
|
|
63
|
+
execute: () => setTheme("light"),
|
|
64
|
+
icon: "Sun"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: "switch-to-dark-theme",
|
|
68
|
+
parentActionId: pageId,
|
|
69
|
+
label: "Switch to dark theme",
|
|
70
|
+
groupLabel: "Studio",
|
|
71
|
+
checkIfAvailable: () => theme !== "dark",
|
|
72
|
+
execute: () => setTheme("dark"),
|
|
73
|
+
icon: "Moon"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: "switch-to-system-theme",
|
|
77
|
+
parentActionId: pageId,
|
|
78
|
+
label: "Switch to system theme",
|
|
79
|
+
groupLabel: "Studio",
|
|
80
|
+
checkIfAvailable: () => theme !== "system",
|
|
81
|
+
execute: () => setTheme("system"),
|
|
82
|
+
icon: "Monitor"
|
|
83
|
+
}
|
|
84
|
+
];
|
|
85
|
+
actionsStore.send({
|
|
86
|
+
type: "registerManyActions",
|
|
87
|
+
actions
|
|
88
|
+
});
|
|
89
|
+
return () => {
|
|
90
|
+
actionsStore.send({
|
|
91
|
+
type: "unregisterManyActions",
|
|
92
|
+
ids: actions.map((a) => a.id)
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
}, [theme, setTheme]);
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
export { useTheme, useThemeActions };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"appGeneration.d.ts","sourceRoot":"","sources":["../../../src/features/vite/appGeneration.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AA6C1C,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,QAI9C;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,QA6BlE"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { writeIfChanged } from "./utils.js";
|
|
2
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { relative, resolve } from "node:path";
|
|
4
|
+
//#region src/features/vite/appGeneration.ts
|
|
5
|
+
var HEADER = `/* ============================================================================
|
|
6
|
+
* AUTO-GENERATED BY CAMOX — DO NOT EDIT
|
|
7
|
+
*
|
|
8
|
+
* This file is managed by the Camox Vite plugin and should stay gitignored.
|
|
9
|
+
* Any manual edits will be automatically reverted by the dev server.
|
|
10
|
+
* ============================================================================ */
|
|
11
|
+
|
|
12
|
+
`;
|
|
13
|
+
function generateCamoxApp() {
|
|
14
|
+
return HEADER + `import { createApp } from 'camox/createApp';
|
|
15
|
+
import type { Block } from 'camox/createBlock';
|
|
16
|
+
import type { Layout } from 'camox/createLayout';
|
|
17
|
+
|
|
18
|
+
// Auto-import all blocks from the blocks directory
|
|
19
|
+
const blockModules = import.meta.glob<{ block: Block }>('./blocks/*.{ts,tsx}', {
|
|
20
|
+
eager: true,
|
|
21
|
+
});
|
|
22
|
+
const blocks = Object.values(blockModules).map((mod) => mod.block);
|
|
23
|
+
|
|
24
|
+
// Auto-import all layouts from the layouts directory
|
|
25
|
+
const layoutModules = import.meta.glob<{ layout: Layout }>(
|
|
26
|
+
'./layouts/*.{ts,tsx}',
|
|
27
|
+
{ eager: true },
|
|
28
|
+
);
|
|
29
|
+
const layouts = Object.values(layoutModules).map((mod) => mod.layout);
|
|
30
|
+
|
|
31
|
+
export const camoxApp = createApp({
|
|
32
|
+
blocks,
|
|
33
|
+
layouts,
|
|
34
|
+
});
|
|
35
|
+
`;
|
|
36
|
+
}
|
|
37
|
+
function getAppFileEntries(appRoot) {
|
|
38
|
+
return [{
|
|
39
|
+
path: resolve(appRoot, "src/camox/app.ts"),
|
|
40
|
+
content: generateCamoxApp()
|
|
41
|
+
}];
|
|
42
|
+
}
|
|
43
|
+
function generateAppFile(appRoot) {
|
|
44
|
+
for (const entry of getAppFileEntries(appRoot)) writeIfChanged(entry.path, entry.content);
|
|
45
|
+
}
|
|
46
|
+
function watchAppFile(server, appRoot) {
|
|
47
|
+
const entries = getAppFileEntries(appRoot);
|
|
48
|
+
const expectedByPath = new Map(entries.map((e) => [e.path, e.content]));
|
|
49
|
+
server.watcher.on("change", (changedPath) => {
|
|
50
|
+
const expected = expectedByPath.get(changedPath);
|
|
51
|
+
if (!expected) return;
|
|
52
|
+
if (readFileSync(changedPath, "utf-8") !== expected) {
|
|
53
|
+
const rel = relative(server.config.root, changedPath);
|
|
54
|
+
server.config.logger.warn(`Camox app file "${rel}" was modified — reverting to generated version.`, { timestamp: true });
|
|
55
|
+
writeFileSync(changedPath, expected, "utf-8");
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
server.watcher.on("unlink", (deletedPath) => {
|
|
59
|
+
const expected = expectedByPath.get(deletedPath);
|
|
60
|
+
if (!expected) return;
|
|
61
|
+
const rel = relative(server.config.root, deletedPath);
|
|
62
|
+
server.config.logger.warn(`Camox app file "${rel}" was deleted — recreating.`, { timestamp: true });
|
|
63
|
+
writeFileSync(deletedPath, expected, "utf-8");
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
export { generateAppFile, watchAppFile };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blockBoilerplate.d.ts","sourceRoot":"","sources":["../../../src/features/vite/blockBoilerplate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAoD1C,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,QA4BvD"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { basename, resolve } from "node:path";
|
|
3
|
+
//#region src/features/vite/blockBoilerplate.ts
|
|
4
|
+
var MAX_EMPTY_BLOCK_CHARACTER_COUNT = 50;
|
|
5
|
+
function kebabToCamel(str) {
|
|
6
|
+
return str.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
7
|
+
}
|
|
8
|
+
function kebabToPascal(str) {
|
|
9
|
+
const camel = kebabToCamel(str);
|
|
10
|
+
return camel.charAt(0).toUpperCase() + camel.slice(1);
|
|
11
|
+
}
|
|
12
|
+
function kebabToTitle(str) {
|
|
13
|
+
return str.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
14
|
+
}
|
|
15
|
+
function getBlockBoilerplate(filename) {
|
|
16
|
+
const name = filename.replace(/\.tsx?$/, "");
|
|
17
|
+
const camelName = kebabToCamel(name);
|
|
18
|
+
const pascalName = kebabToPascal(name);
|
|
19
|
+
return `import { Type, createBlock } from "camox/createBlock";
|
|
20
|
+
|
|
21
|
+
const ${camelName} = createBlock({
|
|
22
|
+
id: "${name}",
|
|
23
|
+
title: "${kebabToTitle(name)}",
|
|
24
|
+
description: "Describe when the AI should use this block.",
|
|
25
|
+
content: {
|
|
26
|
+
title: Type.String({ default: "Title" }),
|
|
27
|
+
},
|
|
28
|
+
component: ${pascalName}Component,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
function ${pascalName}Component() {
|
|
32
|
+
return (
|
|
33
|
+
<section>
|
|
34
|
+
<${camelName}.Field name="title">
|
|
35
|
+
{(content) => <h1>{content}</h1>}
|
|
36
|
+
</${camelName}.Field>
|
|
37
|
+
</section>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export { ${camelName} as block };
|
|
42
|
+
`;
|
|
43
|
+
}
|
|
44
|
+
function watchNewBlockFiles(server) {
|
|
45
|
+
const blocksDir = resolve(server.config.root, "src/camox/blocks");
|
|
46
|
+
server.watcher.on("add", (filePath) => {
|
|
47
|
+
if (filePath.startsWith(blocksDir) && /\.tsx?$/.test(filePath) && !filePath.includes("index.")) try {
|
|
48
|
+
if (readFileSync(filePath, "utf-8").trim().length < MAX_EMPTY_BLOCK_CHARACTER_COUNT) {
|
|
49
|
+
const filename = basename(filePath);
|
|
50
|
+
writeFileSync(filePath, getBlockBoilerplate(filename));
|
|
51
|
+
server.config.logger.info(`[camox] Auto-filled block boilerplate: ${filename}`, { timestamp: true });
|
|
52
|
+
}
|
|
53
|
+
} catch {
|
|
54
|
+
server.config.logger.error(`[camox] Could not auto-fill boilerplate at path ${filePath}`, { timestamp: true });
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
export { watchNewBlockFiles };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ViteDevServer } from 'vite';
|
|
2
|
+
export declare const LOCAL_CONVEX_URL = "http://127.0.0.1:3210";
|
|
3
|
+
export declare const LOCAL_CONVEX_SITE_URL = "http://127.0.0.1:3211";
|
|
4
|
+
export declare function startConvexDev(server: ViteDevServer): Promise<void>;
|
|
5
|
+
export declare function stopConvexDev(): void;
|
|
6
|
+
//# sourceMappingURL=convexSync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convexSync.d.ts","sourceRoot":"","sources":["../../../src/features/vite/convexSync.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAE1C,eAAO,MAAM,gBAAgB,0BAA0B,CAAC;AACxD,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAwB7D,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA4EnE;AAED,wBAAgB,aAAa,IAAI,IAAI,CAKpC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
//#region src/features/vite/convexSync.ts
|
|
6
|
+
var LOCAL_CONVEX_URL = "http://127.0.0.1:3210";
|
|
7
|
+
var LOCAL_CONVEX_SITE_URL = "http://127.0.0.1:3211";
|
|
8
|
+
var convexProcess = null;
|
|
9
|
+
function getBackendDir() {
|
|
10
|
+
return dirname(createRequire(import.meta.url).resolve("@camox/backend-content/package.json"));
|
|
11
|
+
}
|
|
12
|
+
/** Parse team and project slugs from .env.local CONVEX_DEPLOYMENT comment */
|
|
13
|
+
function parseDeploymentInfo(backendDir) {
|
|
14
|
+
try {
|
|
15
|
+
const match = readFileSync(join(backendDir, ".env.local"), "utf-8").match(/CONVEX_DEPLOYMENT=.*#\s*team:\s*(\S+),\s*project:\s*(\S+)/);
|
|
16
|
+
if (match) return {
|
|
17
|
+
team: match[1],
|
|
18
|
+
project: match[2]
|
|
19
|
+
};
|
|
20
|
+
} catch {}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
function startConvexDev(server) {
|
|
24
|
+
const cwd = getBackendDir();
|
|
25
|
+
const log = (msg) => server.config.logger.info(`[convex] ${msg}`, { timestamp: true });
|
|
26
|
+
const deploymentInfo = parseDeploymentInfo(cwd);
|
|
27
|
+
if (!deploymentInfo) {
|
|
28
|
+
log("Could not parse team/project from .env.local — skipping local Convex backend");
|
|
29
|
+
return Promise.resolve();
|
|
30
|
+
}
|
|
31
|
+
const args = [
|
|
32
|
+
"convex",
|
|
33
|
+
"dev",
|
|
34
|
+
"--configure",
|
|
35
|
+
"existing",
|
|
36
|
+
"--team",
|
|
37
|
+
deploymentInfo.team,
|
|
38
|
+
"--project",
|
|
39
|
+
deploymentInfo.project,
|
|
40
|
+
"--dev-deployment",
|
|
41
|
+
"local",
|
|
42
|
+
"--local-force-upgrade"
|
|
43
|
+
];
|
|
44
|
+
log(`Starting: npx ${args.join(" ")}`);
|
|
45
|
+
log(`Working directory: ${cwd}`);
|
|
46
|
+
return new Promise((resolve) => {
|
|
47
|
+
convexProcess = spawn("npx", args, {
|
|
48
|
+
cwd,
|
|
49
|
+
stdio: [
|
|
50
|
+
"ignore",
|
|
51
|
+
"pipe",
|
|
52
|
+
"pipe"
|
|
53
|
+
],
|
|
54
|
+
shell: true
|
|
55
|
+
});
|
|
56
|
+
log(`Spawned process with PID: ${convexProcess.pid}`);
|
|
57
|
+
let resolved = false;
|
|
58
|
+
const handleOutput = (stream) => (data) => {
|
|
59
|
+
const lines = data.toString().trim().split("\n");
|
|
60
|
+
for (const line of lines) {
|
|
61
|
+
if (!line.trim()) continue;
|
|
62
|
+
log(`[${stream}] ${line}`);
|
|
63
|
+
if (!resolved && /convex functions ready|watching for changes/i.test(line)) {
|
|
64
|
+
log("Backend ready");
|
|
65
|
+
resolved = true;
|
|
66
|
+
resolve();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
convexProcess.stdout?.on("data", handleOutput("stdout"));
|
|
71
|
+
convexProcess.stderr?.on("data", handleOutput("stderr"));
|
|
72
|
+
convexProcess.on("error", (err) => {
|
|
73
|
+
log(`Process error: ${err.message}`);
|
|
74
|
+
if (!resolved) {
|
|
75
|
+
resolved = true;
|
|
76
|
+
resolve();
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
convexProcess.on("close", (code, signal) => {
|
|
80
|
+
log(`Process exited with code=${code} signal=${signal}`);
|
|
81
|
+
if (!resolved) {
|
|
82
|
+
resolved = true;
|
|
83
|
+
resolve();
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
server.httpServer?.on("close", () => {
|
|
87
|
+
stopConvexDev();
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function stopConvexDev() {
|
|
92
|
+
if (convexProcess) {
|
|
93
|
+
convexProcess.kill();
|
|
94
|
+
convexProcess = null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
export { LOCAL_CONVEX_SITE_URL, LOCAL_CONVEX_URL, startConvexDev, stopConvexDev };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ViteDevServer } from 'vite';
|
|
2
|
+
export interface DefinitionsSyncOptions {
|
|
3
|
+
/** Stable project slug used to resolve the project */
|
|
4
|
+
projectSlug?: string;
|
|
5
|
+
/** Path to the module that exports the camoxApp (relative to project root) */
|
|
6
|
+
camoxAppPath?: string;
|
|
7
|
+
/** Convex URL to connect to for syncing definitions */
|
|
8
|
+
convexUrl?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function syncDefinitions(server: ViteDevServer, options?: DefinitionsSyncOptions): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=definitionsSync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definitionsSync.d.ts","sourceRoot":"","sources":["../../../src/features/vite/definitionsSync.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAO1C,MAAM,WAAW,sBAAsB;IACrC,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAOD,wBAAsB,eAAe,CACnC,MAAM,EAAE,aAAa,EACrB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,IAAI,CAAC,CAmOf"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { api } from "camox/server/api";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { ConvexClient } from "convex/browser";
|
|
4
|
+
//#region src/features/vite/definitionsSync.ts
|
|
5
|
+
var SYNC_DEBOUNCE_DELAY_MS = 100;
|
|
6
|
+
function getBlockIdFromFilePath(filePath) {
|
|
7
|
+
return path.basename(filePath, path.extname(filePath));
|
|
8
|
+
}
|
|
9
|
+
async function syncDefinitions(server, options = {}) {
|
|
10
|
+
const camoxAppPath = options.camoxAppPath ?? "./src/camox/app.ts";
|
|
11
|
+
const blocksDir = path.resolve(server.config.root, "src/camox/blocks");
|
|
12
|
+
if (!options.projectSlug) {
|
|
13
|
+
server.config.logger.warn("[camox] No projectSlug provided, skipping block definitions sync", { timestamp: true });
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const projectSlug = options.projectSlug;
|
|
17
|
+
const convexUrl = options.convexUrl ?? process.env.VITE_CONVEX_URL;
|
|
18
|
+
if (!convexUrl) {
|
|
19
|
+
server.config.logger.warn("[camox] No Convex URL provided, skipping block definitions sync", { timestamp: true });
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const client = new ConvexClient(convexUrl);
|
|
23
|
+
async function getProjectId() {
|
|
24
|
+
const project = await client.query(api.projects.getProjectBySlug, { slug: projectSlug });
|
|
25
|
+
if (!project) {
|
|
26
|
+
server.config.logger.warn(`[camox] No project found with slug "${projectSlug}", skipping block definitions sync`, { timestamp: true });
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
return project._id;
|
|
30
|
+
}
|
|
31
|
+
async function performInitialSync() {
|
|
32
|
+
const camoxModule = await server.ssrLoadModule(camoxAppPath);
|
|
33
|
+
if (!camoxModule.camoxApp) {
|
|
34
|
+
server.config.logger.warn(`[camox] No camoxApp export found in ${camoxAppPath}`, { timestamp: true });
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const projectId = await getProjectId();
|
|
38
|
+
if (!projectId) return;
|
|
39
|
+
const definitions = camoxModule.camoxApp.getBlocks().map((block) => ({
|
|
40
|
+
blockId: block.id,
|
|
41
|
+
title: block.title,
|
|
42
|
+
description: block.description,
|
|
43
|
+
contentSchema: block.contentSchema,
|
|
44
|
+
settingsSchema: block.settingsSchema,
|
|
45
|
+
layoutOnly: block.layoutOnly || void 0
|
|
46
|
+
}));
|
|
47
|
+
await client.mutation(api.blockDefinitions.syncBlockDefinitions, {
|
|
48
|
+
projectId,
|
|
49
|
+
definitions
|
|
50
|
+
});
|
|
51
|
+
server.config.logger.info(`[camox] Synced ${definitions.length} block definition${definitions.length === 1 ? "" : "s"}`, { timestamp: true });
|
|
52
|
+
const layoutDefinitions = camoxModule.camoxApp.getSerializableLayoutDefinitions();
|
|
53
|
+
if (layoutDefinitions.length > 0) {
|
|
54
|
+
await client.mutation(api.layouts.syncLayouts, {
|
|
55
|
+
projectId,
|
|
56
|
+
layouts: layoutDefinitions
|
|
57
|
+
});
|
|
58
|
+
server.config.logger.info(`[camox] Synced ${layoutDefinitions.length} layout${layoutDefinitions.length === 1 ? "" : "s"}`, { timestamp: true });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async function upsertBlock(filePath) {
|
|
62
|
+
const relativePath = "./" + path.relative(server.config.root, filePath);
|
|
63
|
+
const moduleNode = server.moduleGraph.getModuleById(relativePath);
|
|
64
|
+
if (moduleNode) server.moduleGraph.invalidateModule(moduleNode);
|
|
65
|
+
const blockModule = await server.ssrLoadModule(relativePath);
|
|
66
|
+
if (!blockModule.block) {
|
|
67
|
+
server.config.logger.warn(`[camox] No block export found in ${relativePath}`, { timestamp: true });
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const block = blockModule.block;
|
|
71
|
+
const projectId = await getProjectId();
|
|
72
|
+
if (!projectId) return;
|
|
73
|
+
const result = await client.mutation(api.blockDefinitions.upsertBlockDefinition, {
|
|
74
|
+
projectId,
|
|
75
|
+
blockId: block.id,
|
|
76
|
+
title: block.title,
|
|
77
|
+
description: block.description,
|
|
78
|
+
contentSchema: block.contentSchema,
|
|
79
|
+
settingsSchema: block.settingsSchema,
|
|
80
|
+
layoutOnly: block.layoutOnly || void 0
|
|
81
|
+
});
|
|
82
|
+
server.config.logger.info(`[camox] ${result.action === "created" ? "Created" : "Updated"} block "${block.id}"`, { timestamp: true });
|
|
83
|
+
}
|
|
84
|
+
async function deleteBlock(filePath) {
|
|
85
|
+
const blockId = getBlockIdFromFilePath(filePath);
|
|
86
|
+
const projectId = await getProjectId();
|
|
87
|
+
if (!projectId) return;
|
|
88
|
+
if ((await client.mutation(api.blockDefinitions.deleteBlockDefinition, {
|
|
89
|
+
projectId,
|
|
90
|
+
blockId
|
|
91
|
+
})).deleted) server.config.logger.info(`[camox] Deleted block "${blockId}"`, { timestamp: true });
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
await performInitialSync();
|
|
95
|
+
} catch (error) {
|
|
96
|
+
server.config.logger.error(`[camox] Failed to sync block definitions: ${error}`, { timestamp: true });
|
|
97
|
+
}
|
|
98
|
+
const debounceTimers = /* @__PURE__ */ new Map();
|
|
99
|
+
const layoutsDir = path.resolve(server.config.root, "src/camox/layouts");
|
|
100
|
+
function isBlockFile(filePath) {
|
|
101
|
+
return filePath.startsWith(blocksDir) && /\.tsx?$/.test(filePath);
|
|
102
|
+
}
|
|
103
|
+
function isLayoutFile(filePath) {
|
|
104
|
+
return filePath.startsWith(layoutsDir) && /\.tsx?$/.test(filePath);
|
|
105
|
+
}
|
|
106
|
+
const handleBlockFileUpsert = (filePath) => {
|
|
107
|
+
if (!isBlockFile(filePath)) return;
|
|
108
|
+
const existingTimer = debounceTimers.get(filePath);
|
|
109
|
+
if (existingTimer) clearTimeout(existingTimer);
|
|
110
|
+
debounceTimers.set(filePath, setTimeout(async () => {
|
|
111
|
+
debounceTimers.delete(filePath);
|
|
112
|
+
try {
|
|
113
|
+
await upsertBlock(filePath);
|
|
114
|
+
} catch (error) {
|
|
115
|
+
server.config.logger.error(`[camox] Failed to sync block: ${error}`, { timestamp: true });
|
|
116
|
+
}
|
|
117
|
+
}, SYNC_DEBOUNCE_DELAY_MS));
|
|
118
|
+
};
|
|
119
|
+
const handleBlockFileDelete = (filePath) => {
|
|
120
|
+
if (!isBlockFile(filePath)) return;
|
|
121
|
+
const existingTimer = debounceTimers.get(filePath);
|
|
122
|
+
if (existingTimer) {
|
|
123
|
+
clearTimeout(existingTimer);
|
|
124
|
+
debounceTimers.delete(filePath);
|
|
125
|
+
}
|
|
126
|
+
setTimeout(async () => {
|
|
127
|
+
try {
|
|
128
|
+
await deleteBlock(filePath);
|
|
129
|
+
} catch (error) {
|
|
130
|
+
server.config.logger.error(`[camox] Failed to delete block: ${error}`, { timestamp: true });
|
|
131
|
+
}
|
|
132
|
+
}, SYNC_DEBOUNCE_DELAY_MS);
|
|
133
|
+
};
|
|
134
|
+
let layoutSyncTimer = null;
|
|
135
|
+
const handleLayoutFileChange = (filePath) => {
|
|
136
|
+
if (!isLayoutFile(filePath)) return;
|
|
137
|
+
if (layoutSyncTimer) clearTimeout(layoutSyncTimer);
|
|
138
|
+
layoutSyncTimer = setTimeout(async () => {
|
|
139
|
+
layoutSyncTimer = null;
|
|
140
|
+
try {
|
|
141
|
+
await performInitialSync();
|
|
142
|
+
} catch (error) {
|
|
143
|
+
server.config.logger.error(`[camox] Failed to sync layouts: ${error}`, { timestamp: true });
|
|
144
|
+
}
|
|
145
|
+
}, SYNC_DEBOUNCE_DELAY_MS);
|
|
146
|
+
};
|
|
147
|
+
server.watcher.on("change", handleBlockFileUpsert);
|
|
148
|
+
server.watcher.on("change", handleLayoutFileChange);
|
|
149
|
+
server.watcher.on("add", handleBlockFileUpsert);
|
|
150
|
+
server.watcher.on("add", handleLayoutFileChange);
|
|
151
|
+
server.watcher.on("unlink", handleBlockFileDelete);
|
|
152
|
+
server.httpServer?.on("close", () => {
|
|
153
|
+
client.close();
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
//#endregion
|
|
157
|
+
export { syncDefinitions };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ViteDevServer } from 'vite';
|
|
2
|
+
export declare function generateRouteFiles(routesDir: string, convexUrl: string, managementUrl: string): void;
|
|
3
|
+
export declare function watchRouteFiles(server: ViteDevServer, routesDir: string, convexUrl: string, managementUrl: string): void;
|
|
4
|
+
//# sourceMappingURL=routeGeneration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routeGeneration.d.ts","sourceRoot":"","sources":["../../../src/features/vite/routeGeneration.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAoL1C,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,QAO7F;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,QA8BtB"}
|