diff --git a/.gitignore b/.gitignore index 7a3c37870..de1011213 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,9 @@ apps/*/locales apps/*/package.json build tsbuild +storybook-static +**/storybook-static + *.js !eslint.config.js *.tsbuildinfo @@ -21,6 +24,7 @@ pb_*/ medium .temp server/src/generated +.turbo # system files Thumbs.db diff --git a/.prettierignore b/.prettierignore index b17149b31..661ad1343 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1 +1,5 @@ -*.mdx \ No newline at end of file +*.mdx +dist/ +**/dist/ +storybook-static/ +**/storybook-static/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 8fdc3d4ca..156ca6eff 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,4 +13,4 @@ "typescript.tsdk": "node_modules/typescript/lib", "js/ts.tsdk.path": "node_modules/typescript/lib", "js/ts.experimental.useTsgo": true -} \ No newline at end of file +} diff --git a/bun.lock b/bun.lock index 1bc97e9a9..2c5958545 100644 --- a/bun.lock +++ b/bun.lock @@ -54,6 +54,7 @@ "eslint-plugin-unused-imports": "^4.2.0", "globals": "^16.5.0", "prettier": "^3.8.0", + "turbo": "^2.0.4", "typescript": "^5.9.3", "typescript-eslint": "^8.31.1", "vite": "^7.1.9", @@ -460,6 +461,7 @@ "version": "0.0.0", "dependencies": { "@lifeforge/log": "workspace:*", + "@lifeforge/server-utils": "workspace:*", "chalk": "^5.6.2", "commander": "^14.0.2", "concurrently": "^9.2.1", @@ -1080,6 +1082,18 @@ "@tsconfig/svelte": ["@tsconfig/svelte@1.0.13", "", {}, "sha512-5lYJP45Xllo4yE/RUBccBT32eBlRDbqN8r1/MIvQbKxW3aFqaYPCNgm8D5V20X4ShHcwvYWNlKg3liDh1MlBoA=="], + "@turbo/darwin-64": ["@turbo/darwin-64@2.9.16", "", { "os": "darwin", "cpu": "x64" }, "sha512-jLjApWTSNd7JZ5JaLYfelW1ytnGQOvB7ivl+2RD1xQvJTbi8I9gBjzcga7tDZVPyaxpl10YTfJt3BrYXR18KDw=="], + + "@turbo/darwin-arm64": ["@turbo/darwin-arm64@2.9.16", "", { "os": "darwin", "cpu": "arm64" }, "sha512-YPgrn+5HIGzrx0O2a631SV4MBQUe4W/DafMFUuBVgaU32PW9/OTT0ehviF0QSxTXuRJlHvW2eUTemddF5/spmw=="], + + "@turbo/linux-64": ["@turbo/linux-64@2.9.16", "", { "os": "linux", "cpu": "x64" }, "sha512-vAEf1H6l26lTpl9FJ/peQo1NUB8RC0sbEJJz5mPcUhHA2bPDup2x3CZPgo/bH8S4cUcBLm4FN3UHd5iUO2RAew=="], + + "@turbo/linux-arm64": ["@turbo/linux-arm64@2.9.16", "", { "os": "linux", "cpu": "arm64" }, "sha512-xDBLR2PZg4BrQOchfG6svgpv5FCNJ2TOtT2psLdEJcdKo1BH+pnPs9Xj6pvUjgfkHbuvBOfeE4R6tvxMoQKDHQ=="], + + "@turbo/windows-64": ["@turbo/windows-64@2.9.16", "", { "os": "win32", "cpu": "x64" }, "sha512-NBAJnaUiGdgkSzQwUIdOvkCkcpTSu58G/sBGa0mvBtzfvFOOgrQwepKOOQ8cp6sWM6OcKDNFj2p1dsZA1OWjPg=="], + + "@turbo/windows-arm64": ["@turbo/windows-arm64@2.9.16", "", { "os": "win32", "cpu": "arm64" }, "sha512-Y7SJppD0Z8wjO3Ec0ZGd9KQ4Yv0BMnA8CIowj5Vp+OEVsosXDG2weK6/t1RRLfJmc2Ozrnd6y4DOgQys+mn3WQ=="], + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg=="], "@types/argparse": ["@types/argparse@1.0.38", "", {}, "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA=="], @@ -3632,6 +3646,8 @@ "tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="], + "turbo": ["turbo@2.9.16", "", { "optionalDependencies": { "@turbo/darwin-64": "2.9.16", "@turbo/darwin-arm64": "2.9.16", "@turbo/linux-64": "2.9.16", "@turbo/linux-arm64": "2.9.16", "@turbo/windows-64": "2.9.16", "@turbo/windows-arm64": "2.9.16" }, "bin": { "turbo": "bin/turbo" } }, "sha512-NqgRQy6j6dPYcdSdv0q1g9QsZg7SWg87RERM8otw/1AtKU2yTFVClOM7cbwKzOonZr/Ek1blTBucw64L9H0Bwg=="], + "tweetnacl": ["tweetnacl@0.14.5", "", {}, "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="], "type": ["type@2.7.3", "", {}, "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ=="], diff --git a/client/src/core/accountSettings/components/AvatarColumn.tsx b/client/src/core/accountSettings/components/AvatarColumn.tsx index 271d47ff2..84fdf3fcb 100644 --- a/client/src/core/accountSettings/components/AvatarColumn.tsx +++ b/client/src/core/accountSettings/components/AvatarColumn.tsx @@ -1,7 +1,6 @@ import { useMutation } from '@tanstack/react-query' import { useCallback } from 'react' import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' import { useAuth } from '@lifeforge/api' import { @@ -12,6 +11,7 @@ import { Flex, Icon, OptionsColumn, + toast, useModalStore } from '@lifeforge/ui' diff --git a/client/src/core/accountSettings/components/OrdinaryColumn.tsx b/client/src/core/accountSettings/components/OrdinaryColumn.tsx index 147c524b6..c6f6a807b 100644 --- a/client/src/core/accountSettings/components/OrdinaryColumn.tsx +++ b/client/src/core/accountSettings/components/OrdinaryColumn.tsx @@ -51,9 +51,7 @@ function OrdinaryColumn({ } if (type === 'datetime') { - return dayjs(userData[id]).format( - 'DD MMM YYYY' - ) + return dayjs(userData[id]).format('DD MMM YYYY') } return userData[id] diff --git a/client/src/core/accountSettings/components/PasswordColumn.tsx b/client/src/core/accountSettings/components/PasswordColumn.tsx index 58933c1f1..fe13bd0b4 100644 --- a/client/src/core/accountSettings/components/PasswordColumn.tsx +++ b/client/src/core/accountSettings/components/PasswordColumn.tsx @@ -1,8 +1,7 @@ import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' import { usePromiseLoading } from '@lifeforge/api' -import { Button, OptionsColumn } from '@lifeforge/ui' +import { Button, OptionsColumn, toast } from '@lifeforge/ui' import forgeAPI from '@/forgeAPI' diff --git a/client/src/core/accountSettings/components/QRLoginColumn.tsx b/client/src/core/accountSettings/components/QRLoginColumn.tsx index 9548f0eb9..5c5f9427a 100644 --- a/client/src/core/accountSettings/components/QRLoginColumn.tsx +++ b/client/src/core/accountSettings/components/QRLoginColumn.tsx @@ -1,11 +1,11 @@ import { useCallback } from 'react' import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' import { Button, OptionsColumn, QRCodeScanner, + toast, useModalStore } from '@lifeforge/ui' diff --git a/client/src/core/accountSettings/modals/DisableTwoFAModal.tsx b/client/src/core/accountSettings/modals/DisableTwoFAModal.tsx index cb498f6b2..a035eb85e 100644 --- a/client/src/core/accountSettings/modals/DisableTwoFAModal.tsx +++ b/client/src/core/accountSettings/modals/DisableTwoFAModal.tsx @@ -1,8 +1,7 @@ import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' import { useAuth } from '@lifeforge/api' -import { ConfirmationModal } from '@lifeforge/ui' +import { ConfirmationModal, toast } from '@lifeforge/ui' import forgeAPI from '@/forgeAPI' diff --git a/client/src/core/accountSettings/modals/EnableTwoFAModal/components/OTPConfirmScreen.tsx b/client/src/core/accountSettings/modals/EnableTwoFAModal/components/OTPConfirmScreen.tsx index 2746af748..c47efb631 100644 --- a/client/src/core/accountSettings/modals/EnableTwoFAModal/components/OTPConfirmScreen.tsx +++ b/client/src/core/accountSettings/modals/EnableTwoFAModal/components/OTPConfirmScreen.tsx @@ -1,9 +1,8 @@ import { useState } from 'react' import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' import { encrypt } from '@lifeforge/api' -import { Flex, OTPInputBox, Text } from '@lifeforge/ui' +import { Flex, OTPInputBox, Text, toast } from '@lifeforge/ui' import forgeAPI from '@/forgeAPI' diff --git a/client/src/core/accountSettings/modals/EnableTwoFAModal/components/QRCodeDisplay.tsx b/client/src/core/accountSettings/modals/EnableTwoFAModal/components/QRCodeDisplay.tsx index 8886a91d5..227815d7e 100644 --- a/client/src/core/accountSettings/modals/EnableTwoFAModal/components/QRCodeDisplay.tsx +++ b/client/src/core/accountSettings/modals/EnableTwoFAModal/components/QRCodeDisplay.tsx @@ -1,9 +1,14 @@ import { QRCodeSVG } from 'qrcode.react' import { useEffect, useState } from 'react' -import { toast } from '@lifeforge/ui' import { decrypt } from '@lifeforge/api' -import { Box, Flex, LoadingScreen, usePersonalization } from '@lifeforge/ui' +import { + Box, + Flex, + LoadingScreen, + toast, + usePersonalization +} from '@lifeforge/ui' import forgeAPI from '@/forgeAPI' diff --git a/client/src/core/accountSettings/modals/EnableTwoFAModal/index.tsx b/client/src/core/accountSettings/modals/EnableTwoFAModal/index.tsx index 0192dae83..9b18aaa57 100644 --- a/client/src/core/accountSettings/modals/EnableTwoFAModal/index.tsx +++ b/client/src/core/accountSettings/modals/EnableTwoFAModal/index.tsx @@ -1,9 +1,8 @@ import { useCallback } from 'react' import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' import { useAuth } from '@lifeforge/api' -import { Box, ModalHeader } from '@lifeforge/ui' +import { Box, ModalHeader, toast } from '@lifeforge/ui' import TwoFAEnableProcedure from './components/TwoFAEnableProcedure' diff --git a/client/src/core/accountSettings/modals/ModifyModal.tsx b/client/src/core/accountSettings/modals/ModifyModal.tsx index 43bf1e397..06d7c83ec 100644 --- a/client/src/core/accountSettings/modals/ModifyModal.tsx +++ b/client/src/core/accountSettings/modals/ModifyModal.tsx @@ -2,15 +2,15 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useMutation } from '@tanstack/react-query' import _ from 'lodash' import { useForm } from 'react-hook-form' -import { toast } from '@lifeforge/ui' import z from 'zod' -import { useAuth, type UserData } from '@lifeforge/api' +import { type UserData, useAuth } from '@lifeforge/api' import { DateField, FormModal, TextField, - createDefaultValues + createDefaultValues, + toast } from '@lifeforge/ui' import forgeAPI from '@/forgeAPI' @@ -48,6 +48,7 @@ function ModifyModal({ } else { setUserData(oldData => { if (!oldData) return null + return { ...oldData, ...newData.data } as UserData }) } diff --git a/client/src/core/accountSettings/modals/QRLoginScannerModal/hooks/useQRLoginApproval.ts b/client/src/core/accountSettings/modals/QRLoginScannerModal/hooks/useQRLoginApproval.ts index 02fc9cf43..1be16bd49 100644 --- a/client/src/core/accountSettings/modals/QRLoginScannerModal/hooks/useQRLoginApproval.ts +++ b/client/src/core/accountSettings/modals/QRLoginScannerModal/hooks/useQRLoginApproval.ts @@ -1,8 +1,8 @@ import { useState } from 'react' import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' import { usePromiseLoading } from '@lifeforge/api' +import { toast } from '@lifeforge/ui' import forgeAPI from '@/forgeAPI' diff --git a/client/src/core/apiKeys/components/EntryItem.tsx b/client/src/core/apiKeys/components/EntryItem.tsx index c7ae6edf3..604fc2ec6 100644 --- a/client/src/core/apiKeys/components/EntryItem.tsx +++ b/client/src/core/apiKeys/components/EntryItem.tsx @@ -4,7 +4,6 @@ import dayjs from 'dayjs' import relativeTime from 'dayjs/plugin/relativeTime.js' import { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' import { useFederation } from '@lifeforge/federation' import { @@ -19,6 +18,7 @@ import { TAILWIND_PALETTE, TagChip, Text, + toast, useModalStore } from '@lifeforge/ui' diff --git a/client/src/core/apiKeys/modals/ModifyAPIKeyModal.tsx b/client/src/core/apiKeys/modals/ModifyAPIKeyModal.tsx index 1f38eec27..a835fe81a 100644 --- a/client/src/core/apiKeys/modals/ModifyAPIKeyModal.tsx +++ b/client/src/core/apiKeys/modals/ModifyAPIKeyModal.tsx @@ -1,7 +1,6 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useMutation, useQueryClient } from '@tanstack/react-query' import { useForm, useWatch } from 'react-hook-form' -import { toast } from '@lifeforge/ui' import z from 'zod' import { @@ -9,7 +8,8 @@ import { FormModal, IconField, TextField, - createDefaultValues + createDefaultValues, + toast } from '@lifeforge/ui' import forgeAPI from '@/forgeAPI' diff --git a/client/src/core/auth/components/AuthForm.tsx b/client/src/core/auth/components/AuthForm.tsx index 961731700..92a57fba0 100644 --- a/client/src/core/auth/components/AuthForm.tsx +++ b/client/src/core/auth/components/AuthForm.tsx @@ -3,11 +3,9 @@ import { useCallback, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { useSearchParams } from 'react-router' -import { usePromiseLoading } from '@lifeforge/api' +import { useAuth, usePromiseLoading } from '@lifeforge/api' import { Stack, TextInput, toast } from '@lifeforge/ui' -import { useAuth } from '@lifeforge/api' - import AuthSignInButton from './AuthSignInButtons' function AuthForm({ providers }: { providers: string[] }) { diff --git a/client/src/core/auth/components/AuthSignInButtons/components/SigninWithProviderButton.tsx b/client/src/core/auth/components/AuthSignInButtons/components/SigninWithProviderButton.tsx index 7cf4c35b6..931f92799 100644 --- a/client/src/core/auth/components/AuthSignInButtons/components/SigninWithProviderButton.tsx +++ b/client/src/core/auth/components/AuthSignInButtons/components/SigninWithProviderButton.tsx @@ -1,12 +1,11 @@ import _ from 'lodash' import { memo, useCallback } from 'react' -import { toast } from '@lifeforge/ui' +import { useSearchParams } from 'react-router' import { useAuth } from '@lifeforge/api' -import { Button } from '@lifeforge/ui' +import { Button, toast } from '@lifeforge/ui' import forgeAPI from '@/forgeAPI' -import { useSearchParams } from 'react-router' function SigninWithProviderButton({ provider, diff --git a/client/src/core/auth/modals/QRLoginModal/hooks/useQRLoginSession.ts b/client/src/core/auth/modals/QRLoginModal/hooks/useQRLoginSession.ts index 6501429ea..d642fa806 100644 --- a/client/src/core/auth/modals/QRLoginModal/hooks/useQRLoginSession.ts +++ b/client/src/core/auth/modals/QRLoginModal/hooks/useQRLoginSession.ts @@ -1,11 +1,10 @@ import { useCallback, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' import { Socket, io } from 'socket.io-client' import { v4 as uuidv4 } from 'uuid' -import { useAuth } from '@lifeforge/api' -import { useAPIEndpoint } from '@lifeforge/api' +import { useAPIEndpoint, useAuth } from '@lifeforge/api' +import { toast } from '@lifeforge/ui' import forgeAPI from '@/forgeAPI' diff --git a/client/src/core/auth/modals/TwoFAModal/components/UsingEmail.tsx b/client/src/core/auth/modals/TwoFAModal/components/UsingEmail.tsx index ad14ddc54..60e43f093 100644 --- a/client/src/core/auth/modals/TwoFAModal/components/UsingEmail.tsx +++ b/client/src/core/auth/modals/TwoFAModal/components/UsingEmail.tsx @@ -1,9 +1,15 @@ import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' import { useAuth } from '@lifeforge/api' -import { Button, OTPInputBox, Stack, Text, TextInput } from '@lifeforge/ui' +import { + Button, + OTPInputBox, + Stack, + Text, + TextInput, + toast +} from '@lifeforge/ui' import forgeAPI from '@/forgeAPI' diff --git a/client/src/core/auth/modals/TwoFAModal/index.tsx b/client/src/core/auth/modals/TwoFAModal/index.tsx index ad2110c56..d697b22a1 100644 --- a/client/src/core/auth/modals/TwoFAModal/index.tsx +++ b/client/src/core/auth/modals/TwoFAModal/index.tsx @@ -1,9 +1,8 @@ import { useState } from 'react' import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' import { useAuth } from '@lifeforge/api' -import { Button, Flex, ModalHeader } from '@lifeforge/ui' +import { Button, Flex, ModalHeader, toast } from '@lifeforge/ui' import OrAuthWithDivider from '../../components/OrAuthWithDivider' import UsingAuthApp from './components/UsingAuthApp' diff --git a/client/src/core/auth/pages/UserCreationPage.tsx b/client/src/core/auth/pages/UserCreationPage.tsx index 940729474..ff4763e82 100644 --- a/client/src/core/auth/pages/UserCreationPage.tsx +++ b/client/src/core/auth/pages/UserCreationPage.tsx @@ -1,9 +1,16 @@ import { useMutation } from '@tanstack/react-query' import { useState } from 'react' import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' -import { Button, Flex, Icon, Stack, Text, TextInput } from '@lifeforge/ui' +import { + Button, + Flex, + Icon, + Stack, + Text, + TextInput, + toast +} from '@lifeforge/ui' import forgeAPI from '@/forgeAPI' diff --git a/client/src/core/backups/components/BackupItem.tsx b/client/src/core/backups/components/BackupItem.tsx index 624ffac6b..f711e48d1 100644 --- a/client/src/core/backups/components/BackupItem.tsx +++ b/client/src/core/backups/components/BackupItem.tsx @@ -2,7 +2,6 @@ import { useMutation, useQueryClient } from '@tanstack/react-query' import dayjs from 'dayjs' import prettyBytes from 'pretty-bytes' import { useCallback, useState } from 'react' -import { toast } from '@lifeforge/ui' import { Box, @@ -13,6 +12,7 @@ import { Flex, Icon, Text, + toast, useModalStore } from '@lifeforge/ui' diff --git a/client/src/core/backups/components/CreateBackupModal.tsx b/client/src/core/backups/components/CreateBackupModal.tsx index 9d07dfa50..e397c381d 100644 --- a/client/src/core/backups/components/CreateBackupModal.tsx +++ b/client/src/core/backups/components/CreateBackupModal.tsx @@ -2,10 +2,9 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useMutation, useQueryClient } from '@tanstack/react-query' import { useForm } from 'react-hook-form' import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' import z from 'zod' -import { FormModal, TextField, createDefaultValues } from '@lifeforge/ui' +import { FormModal, TextField, createDefaultValues, toast } from '@lifeforge/ui' import forgeAPI from '@/forgeAPI' diff --git a/client/src/core/dashboard/components/DashboardGrid.tsx b/client/src/core/dashboard/components/DashboardGrid.tsx index 62504b251..bbfeb122a 100644 --- a/client/src/core/dashboard/components/DashboardGrid.tsx +++ b/client/src/core/dashboard/components/DashboardGrid.tsx @@ -2,13 +2,13 @@ import { useMemo } from 'react' import { Responsive as ResponsiveGridLayout } from 'react-grid-layout' import { useTranslation } from 'react-i18next' -import { useDivSize } from '@lifeforge/ui' import { Box, EmptyStateScreen, Icon, LoadingScreen, colorWithOpacity, + useDivSize, usePersonalization } from '@lifeforge/ui' diff --git a/client/src/core/dashboard/providers/WidgetProvider.tsx b/client/src/core/dashboard/providers/WidgetProvider.tsx index 037310aa6..4f15a8109 100644 --- a/client/src/core/dashboard/providers/WidgetProvider.tsx +++ b/client/src/core/dashboard/providers/WidgetProvider.tsx @@ -64,6 +64,7 @@ function WidgetProvider({ children }: { children: React.ReactNode }) { if (parsedConfig.success) { const config = parsedConfig.data + const LazyComponent = lazy(widgetImportFn) loadedWidgets[config.id] = { diff --git a/client/src/core/documentation/index.tsx b/client/src/core/documentation/index.tsx index 021321f27..99dabdb40 100644 --- a/client/src/core/documentation/index.tsx +++ b/client/src/core/documentation/index.tsx @@ -1,8 +1,8 @@ import { useEffect } from 'react' import { useTranslation } from 'react-i18next' import { useNavigate } from 'react-router' -import { toast } from '@lifeforge/ui' +import { toast } from '@lifeforge/ui' function index() { const navigate = useNavigate() diff --git a/client/src/core/moduleManager/pages/Categories/components/CategoryItem.tsx b/client/src/core/moduleManager/pages/Categories/components/CategoryItem.tsx index bff796287..b0e91e55a 100644 --- a/client/src/core/moduleManager/pages/Categories/components/CategoryItem.tsx +++ b/client/src/core/moduleManager/pages/Categories/components/CategoryItem.tsx @@ -1,6 +1,5 @@ import { useSortable } from '@dnd-kit/sortable' import { CSS } from '@dnd-kit/utilities' -import { toast } from '@lifeforge/ui' import { useFederation } from '@lifeforge/federation' import { @@ -13,6 +12,7 @@ import { Flex, Text, WithDivide, + toast, useModalStore } from '@lifeforge/ui' diff --git a/client/src/core/moduleManager/pages/Categories/components/ModifyCategoryModal.tsx b/client/src/core/moduleManager/pages/Categories/components/ModifyCategoryModal.tsx index e7eaf9909..54db66939 100644 --- a/client/src/core/moduleManager/pages/Categories/components/ModifyCategoryModal.tsx +++ b/client/src/core/moduleManager/pages/Categories/components/ModifyCategoryModal.tsx @@ -1,7 +1,6 @@ import { useQuery } from '@tanstack/react-query' import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' import { Box, @@ -14,6 +13,7 @@ import { TextInput, WithQuery, WithQueryData, + toast, useModalStore } from '@lifeforge/ui' diff --git a/client/src/core/moduleManager/pages/Categories/components/ModifyTranslationKeyModal.tsx b/client/src/core/moduleManager/pages/Categories/components/ModifyTranslationKeyModal.tsx index 5b0c58b41..85de6cbdc 100644 --- a/client/src/core/moduleManager/pages/Categories/components/ModifyTranslationKeyModal.tsx +++ b/client/src/core/moduleManager/pages/Categories/components/ModifyTranslationKeyModal.tsx @@ -1,9 +1,8 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useForm } from 'react-hook-form' -import { toast } from '@lifeforge/ui' import z from 'zod' -import { FormModal, TextField, createDefaultValues } from '@lifeforge/ui' +import { FormModal, TextField, createDefaultValues, toast } from '@lifeforge/ui' const schema = z.object({ key: z diff --git a/client/src/core/moduleManager/pages/Categories/index.tsx b/client/src/core/moduleManager/pages/Categories/index.tsx index dc810915d..ec07a5ef9 100644 --- a/client/src/core/moduleManager/pages/Categories/index.tsx +++ b/client/src/core/moduleManager/pages/Categories/index.tsx @@ -15,7 +15,6 @@ import { } from '@dnd-kit/sortable' import { useCallback, useEffect, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' import { SYSTEM_CATEGORIES, useFederation } from '@lifeforge/federation' import { @@ -25,6 +24,7 @@ import { ModuleHeader, Stack, Text, + toast, useModalStore } from '@lifeforge/ui' diff --git a/client/src/core/moduleManager/pages/Modules/components/ModuleItem.tsx b/client/src/core/moduleManager/pages/Modules/components/ModuleItem.tsx index 7f1701596..f4dbb5c9b 100644 --- a/client/src/core/moduleManager/pages/Modules/components/ModuleItem.tsx +++ b/client/src/core/moduleManager/pages/Modules/components/ModuleItem.tsx @@ -1,6 +1,5 @@ import { useMutation } from '@tanstack/react-query' import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' import { useAPIOnlineStatus } from '@lifeforge/api' import { useFederation } from '@lifeforge/federation' @@ -16,6 +15,7 @@ import { TagChip, Text, colorWithOpacity, + toast, useModalStore } from '@lifeforge/ui' diff --git a/client/src/core/moduleManager/pages/Modules/index.tsx b/client/src/core/moduleManager/pages/Modules/index.tsx index 265e1e997..62c9bff49 100644 --- a/client/src/core/moduleManager/pages/Modules/index.tsx +++ b/client/src/core/moduleManager/pages/Modules/index.tsx @@ -1,6 +1,5 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useMemo } from 'react' -import { toast } from '@lifeforge/ui' import { useFederation } from '@lifeforge/federation' import { @@ -10,6 +9,7 @@ import { Stack, Text, WithQuery, + toast, usePersonalization } from '@lifeforge/ui' diff --git a/client/src/core/personalization/components/BgImageSelector/index.tsx b/client/src/core/personalization/components/BgImageSelector/index.tsx index f1d608f70..f0a3cf7cf 100644 --- a/client/src/core/personalization/components/BgImageSelector/index.tsx +++ b/client/src/core/personalization/components/BgImageSelector/index.tsx @@ -1,16 +1,16 @@ import { useMutation } from '@tanstack/react-query' import { useCallback } from 'react' import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' -import { usePersonalization } from '@lifeforge/ui' import { Button, ConfirmationModal, FilePickerModal, Flex, OptionsColumn, - useModalStore + toast, + useModalStore, + usePersonalization } from '@lifeforge/ui' import forgeAPI from '@/forgeAPI' diff --git a/client/src/core/personalization/components/BgImageSelector/modals/AdjustBgImageModal/components/ResultShowcase.tsx b/client/src/core/personalization/components/BgImageSelector/modals/AdjustBgImageModal/components/ResultShowcase.tsx index 122191096..5ef0571d9 100644 --- a/client/src/core/personalization/components/BgImageSelector/modals/AdjustBgImageModal/components/ResultShowcase.tsx +++ b/client/src/core/personalization/components/BgImageSelector/modals/AdjustBgImageModal/components/ResultShowcase.tsx @@ -1,4 +1,3 @@ -import { usePersonalization } from '@lifeforge/ui' import { Box, Flex, @@ -6,7 +5,8 @@ import { Stack, Text, colorWithOpacity, - surface + surface, + usePersonalization } from '@lifeforge/ui' import { BG_BLURS } from '../constants/bg_blurs' diff --git a/client/src/core/personalization/components/BgImageSelector/modals/AdjustBgImageModal/index.tsx b/client/src/core/personalization/components/BgImageSelector/modals/AdjustBgImageModal/index.tsx index 8888373e0..63e82df43 100644 --- a/client/src/core/personalization/components/BgImageSelector/modals/AdjustBgImageModal/index.tsx +++ b/client/src/core/personalization/components/BgImageSelector/modals/AdjustBgImageModal/index.tsx @@ -1,8 +1,7 @@ import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' -import { usePersonalization } from '@lifeforge/ui' -import { Button, ModalHeader, Stack } from '@lifeforge/ui' +import { Button, ModalHeader, Stack, usePersonalization } from '@lifeforge/ui' import { useUserPersonalization } from '@/providers/features/UserPersonalizationProvider' diff --git a/client/src/core/personalization/components/BgTempSelector/index.tsx b/client/src/core/personalization/components/BgTempSelector/index.tsx index 974def434..03df9d498 100644 --- a/client/src/core/personalization/components/BgTempSelector/index.tsx +++ b/client/src/core/personalization/components/BgTempSelector/index.tsx @@ -1,14 +1,14 @@ import { useState } from 'react' import { useTranslation } from 'react-i18next' -import { usePersonalization } from '@lifeforge/ui' import { Box, Button, ColorInput, Flex, OptionsColumn, - Text + Text, + usePersonalization } from '@lifeforge/ui' import { useUserPersonalization } from '@/providers/features/UserPersonalizationProvider' diff --git a/client/src/core/personalization/components/BorderRadiusSelector/index.tsx b/client/src/core/personalization/components/BorderRadiusSelector/index.tsx index 8bfa741b0..a0db6b53a 100644 --- a/client/src/core/personalization/components/BorderRadiusSelector/index.tsx +++ b/client/src/core/personalization/components/BorderRadiusSelector/index.tsx @@ -1,13 +1,13 @@ import { useTranslation } from 'react-i18next' -import { usePersonalization } from '@lifeforge/ui' import { Flex, Listbox, ListboxOption, OptionsColumn, Text, - surface + surface, + usePersonalization } from '@lifeforge/ui' import { useUserPersonalization } from '@/providers/features/UserPersonalizationProvider' diff --git a/client/src/core/personalization/components/BorderedSelector.tsx b/client/src/core/personalization/components/BorderedSelector.tsx index e82c743be..8257f8019 100644 --- a/client/src/core/personalization/components/BorderedSelector.tsx +++ b/client/src/core/personalization/components/BorderedSelector.tsx @@ -1,7 +1,6 @@ import { useTranslation } from 'react-i18next' -import { usePersonalization } from '@lifeforge/ui' -import { OptionsColumn, Switch } from '@lifeforge/ui' +import { OptionsColumn, Switch, usePersonalization } from '@lifeforge/ui' import { useUserPersonalization } from '@/providers/features/UserPersonalizationProvider' diff --git a/client/src/core/personalization/components/FontFamilySelector/components/FontFamilySelectorModal/index.tsx b/client/src/core/personalization/components/FontFamilySelector/components/FontFamilySelectorModal/index.tsx index 10a560b7f..d5d329c79 100644 --- a/client/src/core/personalization/components/FontFamilySelector/components/FontFamilySelectorModal/index.tsx +++ b/client/src/core/personalization/components/FontFamilySelector/components/FontFamilySelectorModal/index.tsx @@ -1,9 +1,14 @@ import { useState } from 'react' import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' -import { usePersonalization } from '@lifeforge/ui' -import { Button, ModalHeader, Stack, Tabs } from '@lifeforge/ui' +import { + Button, + ModalHeader, + Stack, + Tabs, + toast, + usePersonalization +} from '@lifeforge/ui' import { useUserPersonalization } from '@/providers/features/UserPersonalizationProvider' diff --git a/client/src/core/personalization/components/FontFamilySelector/components/FontFamilySelectorModal/tabs/custom/components/CustomFontCard.tsx b/client/src/core/personalization/components/FontFamilySelector/components/FontFamilySelectorModal/tabs/custom/components/CustomFontCard.tsx index 8ab03ac8a..c8cddc289 100644 --- a/client/src/core/personalization/components/FontFamilySelector/components/FontFamilySelectorModal/tabs/custom/components/CustomFontCard.tsx +++ b/client/src/core/personalization/components/FontFamilySelector/components/FontFamilySelectorModal/tabs/custom/components/CustomFontCard.tsx @@ -1,8 +1,6 @@ import { useMutation, useQueryClient } from '@tanstack/react-query' import { useTranslation } from 'react-i18next' -import { toast } from '@lifeforge/ui' -import { usePersonalization } from '@lifeforge/ui' import { Box, Card, @@ -15,7 +13,9 @@ import { Text, colorWithOpacity, surface, - useModalStore + toast, + useModalStore, + usePersonalization } from '@lifeforge/ui' import forgeAPI from '@/forgeAPI' diff --git a/client/src/core/personalization/components/FontFamilySelector/components/FontFamilySelectorModal/tabs/custom/components/CustomFontUploadModal.tsx b/client/src/core/personalization/components/FontFamilySelector/components/FontFamilySelectorModal/tabs/custom/components/CustomFontUploadModal.tsx index 120ff908a..e9455c01f 100644 --- a/client/src/core/personalization/components/FontFamilySelector/components/FontFamilySelectorModal/tabs/custom/components/CustomFontUploadModal.tsx +++ b/client/src/core/personalization/components/FontFamilySelector/components/FontFamilySelectorModal/tabs/custom/components/CustomFontUploadModal.tsx @@ -1,7 +1,6 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useMutation, useQueryClient } from '@tanstack/react-query' import { useForm } from 'react-hook-form' -import { toast } from '@lifeforge/ui' import z from 'zod' import { @@ -12,7 +11,8 @@ import { convertFormFileFieldData, createDefaultValues, fileValueSchema, - getFormFileFieldInitialData + getFormFileFieldInitialData, + toast } from '@lifeforge/ui' import forgeAPI from '@/forgeAPI' diff --git a/client/src/core/personalization/components/FontFamilySelector/components/FontFamilySelectorModal/tabs/google/components/FontListItem.tsx b/client/src/core/personalization/components/FontFamilySelector/components/FontFamilySelectorModal/tabs/google/components/FontListItem.tsx index 3f7a57cda..62e973a54 100644 --- a/client/src/core/personalization/components/FontFamilySelector/components/FontFamilySelectorModal/tabs/google/components/FontListItem.tsx +++ b/client/src/core/personalization/components/FontFamilySelector/components/FontFamilySelectorModal/tabs/google/components/FontListItem.tsx @@ -1,6 +1,5 @@ import { useMutation, useQueryClient } from '@tanstack/react-query' import { useEffect } from 'react' -import { toast } from '@lifeforge/ui' import { usePromiseLoading } from '@lifeforge/api' import { @@ -12,7 +11,8 @@ import { Ring, Text, Transition, - surface + surface, + toast } from '@lifeforge/ui' import { diff --git a/client/src/core/personalization/components/FontFamilySelector/index.tsx b/client/src/core/personalization/components/FontFamilySelector/index.tsx index 991a6b66c..f159c698b 100644 --- a/client/src/core/personalization/components/FontFamilySelector/index.tsx +++ b/client/src/core/personalization/components/FontFamilySelector/index.tsx @@ -1,7 +1,6 @@ import { useQuery } from '@tanstack/react-query' import { useTranslation } from 'react-i18next' -import { usePersonalization } from '@lifeforge/ui' import { Box, Button, @@ -10,7 +9,8 @@ import { OptionsColumn, Text, WithQuery, - useModalStore + useModalStore, + usePersonalization } from '@lifeforge/ui' import forgeAPI from '@/forgeAPI' diff --git a/client/src/core/personalization/components/FontScaleSelector.tsx b/client/src/core/personalization/components/FontScaleSelector.tsx index ca60df44b..cf536d229 100644 --- a/client/src/core/personalization/components/FontScaleSelector.tsx +++ b/client/src/core/personalization/components/FontScaleSelector.tsx @@ -1,8 +1,14 @@ import { useState } from 'react' import { useTranslation } from 'react-i18next' -import { usePersonalization } from '@lifeforge/ui' -import { Box, Button, Flex, OptionsColumn, SliderInput } from '@lifeforge/ui' +import { + Box, + Button, + Flex, + OptionsColumn, + SliderInput, + usePersonalization +} from '@lifeforge/ui' import { useUserPersonalization } from '@/providers/features/UserPersonalizationProvider' diff --git a/client/src/core/personalization/components/LanguageSelector.tsx b/client/src/core/personalization/components/LanguageSelector.tsx index f7e33cae0..c4b21cfd1 100644 --- a/client/src/core/personalization/components/LanguageSelector.tsx +++ b/client/src/core/personalization/components/LanguageSelector.tsx @@ -1,7 +1,6 @@ import { useQuery } from '@tanstack/react-query' import { useTranslation } from 'react-i18next' -import { usePersonalization } from '@lifeforge/ui' import { Flex, Icon, @@ -10,7 +9,8 @@ import { OptionsColumn, Text, WithQuery, - surface + surface, + usePersonalization } from '@lifeforge/ui' import forgeAPI from '@/forgeAPI' diff --git a/client/src/core/personalization/components/ThemeColorSelector/index.tsx b/client/src/core/personalization/components/ThemeColorSelector/index.tsx index 756aa609f..78649da2a 100644 --- a/client/src/core/personalization/components/ThemeColorSelector/index.tsx +++ b/client/src/core/personalization/components/ThemeColorSelector/index.tsx @@ -1,14 +1,14 @@ import { useState } from 'react' import { useTranslation } from 'react-i18next' -import { usePersonalization } from '@lifeforge/ui' import { Box, Button, ColorInput, Flex, OptionsColumn, - Text + Text, + usePersonalization } from '@lifeforge/ui' import { useUserPersonalization } from '@/providers/features/UserPersonalizationProvider' diff --git a/client/src/core/personalization/components/ThemeSelector.tsx b/client/src/core/personalization/components/ThemeSelector.tsx index 9146af892..8d9a5313a 100644 --- a/client/src/core/personalization/components/ThemeSelector.tsx +++ b/client/src/core/personalization/components/ThemeSelector.tsx @@ -1,6 +1,5 @@ import { useTranslation } from 'react-i18next' -import { usePersonalization } from '@lifeforge/ui' import { Bordered, Box, @@ -9,7 +8,8 @@ import { Icon, OptionsColumn, Text, - Transition + Transition, + usePersonalization } from '@lifeforge/ui' import { useUserPersonalization } from '@/providers/features/UserPersonalizationProvider' diff --git a/client/src/i18n.ts b/client/src/i18n.ts index e9db39def..41c2c2421 100644 --- a/client/src/i18n.ts +++ b/client/src/i18n.ts @@ -1,8 +1,8 @@ import i18n from 'i18next' import I18NextHttpBackend from 'i18next-http-backend' import { initReactI18next } from 'react-i18next' -import forgeAPI from './forgeAPI'; +import forgeAPI from './forgeAPI' export let AVAILABLE_LANG: { name: string diff --git a/client/src/providers/features/UserPersonalizationProvider.tsx b/client/src/providers/features/UserPersonalizationProvider.tsx index f6e21a4d1..3ca4dce2b 100644 --- a/client/src/providers/features/UserPersonalizationProvider.tsx +++ b/client/src/providers/features/UserPersonalizationProvider.tsx @@ -1,7 +1,7 @@ import { createContext, useContext, useEffect } from 'react' -import { toast } from '@lifeforge/ui' import { useAuth } from '@lifeforge/api' +import { toast } from '@lifeforge/ui' import { type IBackdropFilters, type IDashboardLayout, diff --git a/client/src/providers/index.tsx b/client/src/providers/index.tsx index 13c22f4ca..f802faa65 100644 --- a/client/src/providers/index.tsx +++ b/client/src/providers/index.tsx @@ -5,11 +5,11 @@ import { useMemo } from 'react' import { APIEndpointProvider, APIOnlineStatusProvider, + AuthProvider, EncryptionProvider, SocketProvider } from '@lifeforge/api' import { FederationProvider } from '@lifeforge/federation' -import { AuthProvider } from '@lifeforge/api' import { APIOnlineStatusWrapper, BackgroundProvider, @@ -72,6 +72,7 @@ function Providers() { [EncryptionWrapper], // Provider that handles authentication, very obviously + // Explicitly casted to never due to type inference complexity of forgeAPI [ AuthProvider, { @@ -80,7 +81,7 @@ function Providers() { open(TwoFAModal, {}) } } - ], + ] as never, // Provider that manages the main sidebar state (not the module sidebars, the main one) [MainSidebarStateProvider], // Provider that synchronizes user personalization data with the backend diff --git a/client/src/routes/components/Sidebar/Sidebar.tsx b/client/src/routes/components/Sidebar/Sidebar.tsx index c30965445..4b89ffa36 100644 --- a/client/src/routes/components/Sidebar/Sidebar.tsx +++ b/client/src/routes/components/Sidebar/Sidebar.tsx @@ -1,7 +1,11 @@ import { useState } from 'react' -import { useMainSidebarState } from '@lifeforge/ui' -import { Flex, SidebarItem, Transition } from '@lifeforge/ui' +import { + Flex, + SidebarItem, + Transition, + useMainSidebarState +} from '@lifeforge/ui' import SidebarBottomBar from './SidebarBottomBar' import SidebarEventBanner from './SidebarEventBanner' diff --git a/client/src/routes/components/Sidebar/SidebarBottomBar.tsx b/client/src/routes/components/Sidebar/SidebarBottomBar.tsx index 71ac6bef4..bda697bbd 100644 --- a/client/src/routes/components/Sidebar/SidebarBottomBar.tsx +++ b/client/src/routes/components/Sidebar/SidebarBottomBar.tsx @@ -1,6 +1,5 @@ import { useCallback } from 'react' import { useNavigate } from 'react-router' -import { toast } from '@lifeforge/ui' import { useAuth } from '@lifeforge/api' import { @@ -13,6 +12,7 @@ import { Text, Transition, surface, + toast, useMainSidebarState } from '@lifeforge/ui' diff --git a/client/src/routes/components/Sidebar/SidebarHeader.tsx b/client/src/routes/components/Sidebar/SidebarHeader.tsx index af85dc8c3..d953fe172 100644 --- a/client/src/routes/components/Sidebar/SidebarHeader.tsx +++ b/client/src/routes/components/Sidebar/SidebarHeader.tsx @@ -1,4 +1,3 @@ -import { useMainSidebarState } from '@lifeforge/ui' import { Box, Button, @@ -6,7 +5,8 @@ import { Icon, SearchInput, Text, - surface + surface, + useMainSidebarState } from '@lifeforge/ui' function SidebarHeader({ diff --git a/client/src/routes/components/Sidebar/SidebarItems.tsx b/client/src/routes/components/Sidebar/SidebarItems.tsx index 543b8cdc6..9a201feed 100644 --- a/client/src/routes/components/Sidebar/SidebarItems.tsx +++ b/client/src/routes/components/Sidebar/SidebarItems.tsx @@ -2,6 +2,7 @@ import _ from 'lodash' import { Fragment, useEffect, useMemo, useState } from 'react' import { useLocation } from 'react-router' +import { useAuth } from '@lifeforge/api' import { useFederation } from '@lifeforge/federation' import { Box, @@ -13,8 +14,6 @@ import { useMainSidebarState } from '@lifeforge/ui' -import { useAuth } from '@lifeforge/api' - import MainSidebarTitle from './MainSidebarTitle' function SidebarItems({ query }: { query: string }) { diff --git a/client/src/routes/hooks/useAppRouter.ts b/client/src/routes/hooks/useAppRouter.ts index 3626d6190..e4c36dd56 100644 --- a/client/src/routes/hooks/useAppRouter.ts +++ b/client/src/routes/hooks/useAppRouter.ts @@ -2,8 +2,8 @@ import { useEffect, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import { type DataRouter, createBrowserRouter } from 'react-router' -import { useFederation } from '@lifeforge/federation' import { useAuth } from '@lifeforge/api' +import { useFederation } from '@lifeforge/federation' import { createAuthLoadingConfig, diff --git a/client/src/routes/hooks/useTitleEffect.ts b/client/src/routes/hooks/useTitleEffect.ts index 4b8ac4ad5..7e445712d 100644 --- a/client/src/routes/hooks/useTitleEffect.ts +++ b/client/src/routes/hooks/useTitleEffect.ts @@ -1,8 +1,8 @@ import _ from 'lodash' import { useEffect } from 'react' +import { useLocation } from 'react-router' import { useFederation } from '@lifeforge/federation' -import { useLocation } from 'react-router' function useTitleEffect() { const { modules } = useFederation() diff --git a/client/src/routes/utils/routeBuilder.tsx b/client/src/routes/utils/routeBuilder.tsx index b425e0a16..2cc927ebe 100644 --- a/client/src/routes/utils/routeBuilder.tsx +++ b/client/src/routes/utils/routeBuilder.tsx @@ -1,10 +1,10 @@ import { Suspense } from 'react' +import type { RouteObject } from 'react-router' import type { ModuleCategory, ModuleConfig } from '@lifeforge/federation' import { LoadingScreen, ModalManager, ModuleWrapper } from '@lifeforge/ui' import APIKeyStatusProvider from '@/providers/features/APIKeyStatusProvider' -import type { RouteObject } from 'react-router' interface RouteBuilderOptions { routes: ModuleConfig['routes'] diff --git a/client/tsconfig.json b/client/tsconfig.json index bdfd93888..aceccb063 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -2,17 +2,10 @@ "compilerOptions": { "target": "ES2020", "useDefineForClassFields": true, - "lib": [ - "ES2020", - "DOM", - "DOM.Iterable", - "ES2024.Object" - ], + "lib": ["ES2020", "DOM", "DOM.Iterable", "ES2024.Object"], "module": "ESNext", "skipLibCheck": true, - "types": [ - "node" - ], + "types": ["node"], /* Bundler mode */ "outDir": "${configDir}/tsbuild", "moduleResolution": "bundler", @@ -28,17 +21,9 @@ "composite": true, "rootDir": "../", "paths": { - "@/*": [ - "./src/*" - ], - "@core/*": [ - "../core/*" - ] + "@/*": ["./src/*"], + "@core/*": ["../core/*"] } }, - "include": [ - "./src/**/*", - "./vite.config.ts", - "./contract.ts" - ] -} \ No newline at end of file + "include": ["./src/**/*", "./vite.config.ts", "./contract.ts"] +} diff --git a/docs/plugins/mdxListCountsPlugin.d.ts b/docs/plugins/mdxListCountsPlugin.d.ts new file mode 100644 index 000000000..f1a36dec6 --- /dev/null +++ b/docs/plugins/mdxListCountsPlugin.d.ts @@ -0,0 +1,3 @@ +import type { Plugin } from 'vite'; +declare function mdxListCountsPlugin(): Plugin; +export default mdxListCountsPlugin; diff --git a/docs/plugins/mdxListCountsPlugin.ts b/docs/plugins/mdxListCountsPlugin.ts index f45e62644..b51736015 100644 --- a/docs/plugins/mdxListCountsPlugin.ts +++ b/docs/plugins/mdxListCountsPlugin.ts @@ -3,11 +3,14 @@ import path from 'node:path' import type { Plugin } from 'vite' const VIRTUAL_MODULE_ID = 'virtual:mdx-list-counts' + const RESOLVED_VIRTUAL_MODULE_ID = '\0' + VIRTUAL_MODULE_ID function countListItems(mdxSource: string): number { const listItemRegex = /^[\t ]*- /gm + const matches = mdxSource.match(listItemRegex) + return matches ? matches.length : 0 } @@ -25,6 +28,7 @@ function mdxListCountsPlugin(): Plugin { __dirname, '../src/contents/04.progress/versions' ) + const counts: Record = {} // Read all MDX files recursively @@ -33,13 +37,16 @@ function mdxListCountsPlugin(): Plugin { for (const entry of entries) { const fullPath = path.join(dir, entry.name) + const relativePath = path.join(basePath, entry.name) if (entry.isDirectory()) { readMdxFiles(fullPath, relativePath) } else if (entry.name.endsWith('.mdx')) { const content = fs.readFileSync(fullPath, 'utf-8') + const key = `../versions/${relativePath.replace(/\\/g, '/')}` + counts[key] = countListItems(content) } } @@ -56,8 +63,10 @@ function mdxListCountsPlugin(): Plugin { const module = server.moduleGraph.getModuleById( RESOLVED_VIRTUAL_MODULE_ID ) + if (module) { server.moduleGraph.invalidateModule(module) + return [module] } } diff --git a/docs/src/App.tsx b/docs/src/App.tsx index 2f7429dcb..90d8ce233 100644 --- a/docs/src/App.tsx +++ b/docs/src/App.tsx @@ -1,7 +1,7 @@ import { useEffect } from 'react' import { ErrorBoundary } from 'react-error-boundary' - import { Navigate, RouterProvider, createBrowserRouter } from 'react-router' + import { ErrorScreen, NotFoundScreen } from '@lifeforge/ui' import ROUTES from './Router' diff --git a/docs/src/Router.tsx b/docs/src/Router.tsx index 3398c271c..44d1555fc 100644 --- a/docs/src/Router.tsx +++ b/docs/src/Router.tsx @@ -1,5 +1,4 @@ import _ from 'lodash' - import type { RouteObject } from 'react-router' import { components as COMPONENTS } from './components/MdxComponents' diff --git a/docs/src/components/Boilerplate/components/NavigationBar.tsx b/docs/src/components/Boilerplate/components/NavigationBar.tsx index 7b6ec4040..d96d3a8ce 100644 --- a/docs/src/components/Boilerplate/components/NavigationBar.tsx +++ b/docs/src/components/Boilerplate/components/NavigationBar.tsx @@ -1,7 +1,6 @@ import { Icon } from '@iconify/react' import _ from 'lodash' import { useMemo } from 'react' - import { Link, useLocation } from 'react-router' import ROUTES from '../../../Router' diff --git a/docs/src/components/Boilerplate/index.tsx b/docs/src/components/Boilerplate/index.tsx index 882a31409..082dc77ec 100644 --- a/docs/src/components/Boilerplate/index.tsx +++ b/docs/src/components/Boilerplate/index.tsx @@ -1,7 +1,6 @@ import { Icon } from '@iconify/react' import { useEffect } from 'react' import Scrollbars from 'react-custom-scrollbars' - import { useLocation } from 'react-router' import { BLACKLISTED_PAGES } from '../Rightbar' diff --git a/docs/src/components/Layout.tsx b/docs/src/components/Layout.tsx index 21fd45331..c5536d915 100644 --- a/docs/src/components/Layout.tsx +++ b/docs/src/components/Layout.tsx @@ -1,5 +1,4 @@ import { useState } from 'react' - import { Outlet } from 'react-router' import Boilerplate from './Boilerplate' diff --git a/docs/src/components/Rightbar.tsx b/docs/src/components/Rightbar.tsx index 2a20047e5..b2a881a35 100644 --- a/docs/src/components/Rightbar.tsx +++ b/docs/src/components/Rightbar.tsx @@ -1,7 +1,6 @@ import { Icon } from '@iconify/react' import _ from 'lodash' import { useEffect, useRef, useState } from 'react' - import { useLocation } from 'react-router' export const BLACKLISTED_PAGES = ['/progress/changelog'] diff --git a/docs/src/components/Sidebar.tsx b/docs/src/components/Sidebar.tsx index 590c578db..a62396417 100644 --- a/docs/src/components/Sidebar.tsx +++ b/docs/src/components/Sidebar.tsx @@ -1,6 +1,5 @@ import _ from 'lodash' import { Scrollbars } from 'react-custom-scrollbars' - import { Link, useLocation } from 'react-router' import ROUTES from '../Router' diff --git a/docs/src/contents/02.user-guide/components/CustomColorInput.tsx b/docs/src/contents/02.user-guide/components/CustomColorInput.tsx index ca491b58a..243641da5 100644 --- a/docs/src/contents/02.user-guide/components/CustomColorInput.tsx +++ b/docs/src/contents/02.user-guide/components/CustomColorInput.tsx @@ -1,8 +1,7 @@ import { Icon } from '@iconify/react' import { useEffect, useState } from 'react' -import { usePersonalization } from '@lifeforge/ui' -import { Button, ColorInput, Switch } from '@lifeforge/ui' +import { Button, ColorInput, Switch, usePersonalization } from '@lifeforge/ui' function CustomColorInput() { const [color, setColor] = useState('#a9d066') diff --git a/docs/src/main.tsx b/docs/src/main.tsx index 9015b83e0..da5d6304d 100644 --- a/docs/src/main.tsx +++ b/docs/src/main.tsx @@ -6,7 +6,7 @@ import { ModalProvider, PersonalizationProvider } from '@lifeforge/ui' import App from './App' import './index.css' -const forgeAPI = createForgeProxy() +const forgeAPI = createForgeProxy({}) ReactDOM.createRoot(document.getElementById('root')!).render( diff --git a/docs/vite.config.d.ts b/docs/vite.config.d.ts index 135c1dc0b..340562aff 100644 --- a/docs/vite.config.d.ts +++ b/docs/vite.config.d.ts @@ -1,2 +1,2 @@ -declare const _default: import('vite').UserConfig -export default _default +declare const _default: import("vite").UserConfig; +export default _default; diff --git a/docs/vite.config.ts b/docs/vite.config.ts index fe4cb64a9..bdf46ba2d 100644 --- a/docs/vite.config.ts +++ b/docs/vite.config.ts @@ -36,6 +36,7 @@ export default defineConfig({ .toString() } else if (id.endsWith('.mdx')) { const mdxPath = id.toString().split('src/')[1] + return `mdx-${mdxPath.replace(/\//g, '-').replace('.mdx', '')}` } } diff --git a/eslint.config.js b/eslint.config.js index 5edec1b09..54a451036 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -12,7 +12,13 @@ import tseslint from 'typescript-eslint' export default [ { - ignores: ['**/*.config.js', '**/dist/', 'dist/', 'tools/src/templates/**'] + ignores: [ + '**/*.config.js', + '**/dist/', + 'dist/', + 'tools/src/templates/**', + '**/storybook-static/' + ] }, { files: ['**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], diff --git a/package.json b/package.json index 00aae4136..645ba756f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,8 @@ { "name": "lifeforge-monorepo", "private": true, + "type": "module", + "packageManager": "bun@1.3.14", "description": "A comprehensive self-hosted all-in-one personal management system", "version": "0.0.0", "license": "CC BY-NC-SA 4.0", @@ -21,13 +23,12 @@ ], "scripts": { "forge": "bun run tools/src/index.ts", - "build-api": "bun --cwd=packages/api run build", - "build-configs": "bun --cwd=packages/configs run build", - "build-federation": "bun --cwd=packages/federation run build", - "build-logger": "bun --cwd=packages/log run build", - "build-server-utils": "bun --cwd=packages/server-utils run build", - "build-ui": "bun --cwd=packages/ui run build", - "postinstall": "bun build-configs && bun build-api && bun build-logger && bun build-server-utils && bun build-ui && bun build-federation" + "build": "turbo build", + "types": "turbo types", + "lint": "eslint . && prettier --check .", + "fix": "eslint . --fix && prettier --write .", + "test": "turbo test", + "postinstall": "turbo build --filter=\"./packages/*\"" }, "keywords": [ "lifeforge" @@ -61,6 +62,7 @@ "eslint-plugin-unused-imports": "^4.2.0", "globals": "^16.5.0", "prettier": "^3.8.0", + "turbo": "^2.0.4", "typescript": "^5.9.3", "typescript-eslint": "^8.31.1", "vite": "^7.1.9" diff --git a/packages/api/src/core/createForgeProxy.ts b/packages/api/src/core/createForgeProxy.ts index 80c429391..5ac21162d 100644 --- a/packages/api/src/core/createForgeProxy.ts +++ b/packages/api/src/core/createForgeProxy.ts @@ -35,7 +35,11 @@ function createForgeProxyInternal( } function getResolvedHost() { - return (contract && globalProxyRegistry.get(contract)?.apiHost) || globalProxyRegistry.apiHost || '' + return ( + (contract && globalProxyRegistry.get(contract)?.apiHost) || + globalProxyRegistry.apiHost || + '' + ) } const endpoint = new ForgeEndpoint( @@ -79,7 +83,10 @@ function createForgeProxyInternal( } if (prop in CORE_HELPERS) { - return createCoreHelper(getResolvedHost(), prop as keyof typeof CORE_HELPERS) + return createCoreHelper( + getResolvedHost(), + prop as keyof typeof CORE_HELPERS + ) } if (prop in endpoint && typeof (endpoint as any)[prop] !== 'undefined') { diff --git a/packages/api/src/core/helpers/config.ts b/packages/api/src/core/helpers/config.ts index d10c42458..897dd6f7b 100644 --- a/packages/api/src/core/helpers/config.ts +++ b/packages/api/src/core/helpers/config.ts @@ -77,5 +77,3 @@ export type CoreHelperReturnTypes = { > > } - - diff --git a/packages/api/src/core/helpers/createCoreHelper.ts b/packages/api/src/core/helpers/createCoreHelper.ts index 9761d6e90..80620600c 100644 --- a/packages/api/src/core/helpers/createCoreHelper.ts +++ b/packages/api/src/core/helpers/createCoreHelper.ts @@ -1,7 +1,6 @@ import type z from 'zod' import type { UntypedEndpointType } from '../../typescript/forge_proxy.types' - import { ForgeEndpoint } from '../forgeEndpoint' import { CORE_HELPERS, type CoreHelperName } from './config' diff --git a/packages/api/src/providers/SocketProvider.tsx b/packages/api/src/providers/SocketProvider.tsx index ca743a27e..70666da34 100644 --- a/packages/api/src/providers/SocketProvider.tsx +++ b/packages/api/src/providers/SocketProvider.tsx @@ -18,11 +18,7 @@ export interface SocketEvent< progress?: P } -export function SocketProvider({ - children -}: { - children: React.ReactNode -}) { +export function SocketProvider({ children }: { children: React.ReactNode }) { const apiHost = useAPIEndpoint() const [socket, setSocket] = useState(null) diff --git a/packages/api/src/typescript/forge_proxy.types.ts b/packages/api/src/typescript/forge_proxy.types.ts index 9013472e4..1b8c79634 100644 --- a/packages/api/src/typescript/forge_proxy.types.ts +++ b/packages/api/src/typescript/forge_proxy.types.ts @@ -142,46 +142,44 @@ export type InferRawOutput = T extends { /** * Extracts the input schema type from a `ForgeEndpoint` instance. */ -export type InferInput> = - T['__type'] extends { - __isForgeContract: true - __input: infer I - __media: infer M - } - ? I extends { - body?: infer B - query?: infer Q - } - ? { - body: M extends null - ? B extends ZodObjectOrIntersection +export type InferInput> = T['__type'] extends { + __isForgeContract: true + __input: infer I + __media: infer M +} + ? I extends { + body?: infer B + query?: infer Q + } + ? { + body: M extends null + ? B extends ZodObjectOrIntersection + ? z.input + : B + : (B extends ZodObjectOrIntersection ? z.input - : B - : (B extends ZodObjectOrIntersection - ? z.input - : B extends undefined - ? {} - : B) & { - [K in keyof M]: { - __type: 'media' - config: M[K] - } + : B extends undefined + ? {} + : B) & { + [K in keyof M]: { + __type: 'media' + config: M[K] } - query: Q extends ZodObjectOrIntersection ? z.input : Q - } - : never + } + query: Q extends ZodObjectOrIntersection ? z.input : Q + } : never + : never /** * Extracts the output (response) type from a `ForgeEndpoint` instance. */ -export type InferOutput> = - T['__type'] extends { - __isForgeContract: true - __output: infer O - } - ? O - : never +export type InferOutput> = T['__type'] extends { + __isForgeContract: true + __output: infer O +} + ? O + : never /** * Constructs a deeply-nested proxy tree from a server route schema. diff --git a/packages/api/tsconfig.json b/packages/api/tsconfig.json index ccda529d3..400d167b7 100644 --- a/packages/api/tsconfig.json +++ b/packages/api/tsconfig.json @@ -1,10 +1,7 @@ { "extends": "@lifeforge/configs/tsconfig/base.json", "compilerOptions": { - "lib": [ - "ESNext", - "DOM" - ], + "lib": ["ESNext", "DOM"], "target": "ESNext", "module": "ESNext", "declaration": true, @@ -15,12 +12,6 @@ "noFallthroughCasesInSwitch": true, "noUncheckedIndexedAccess": true }, - "include": [ - "./src/**/*", - "./contract.ts" - ], - "exclude": [ - "dist", - "node_modules" - ] -} \ No newline at end of file + "include": ["./src/**/*", "./contract.ts"], + "exclude": ["dist", "node_modules"] +} diff --git a/packages/configs/src/index.ts b/packages/configs/src/index.ts index 1233c6800..cc802a358 100644 --- a/packages/configs/src/index.ts +++ b/packages/configs/src/index.ts @@ -1,2 +1,3 @@ export * from './interfaces/widget_config.types' + export * from './interfaces/module_config.types' diff --git a/packages/configs/src/interfaces/module_config.types.ts b/packages/configs/src/interfaces/module_config.types.ts index bfc72d832..af488488b 100644 --- a/packages/configs/src/interfaces/module_config.types.ts +++ b/packages/configs/src/interfaces/module_config.types.ts @@ -1,7 +1,7 @@ +import type React from 'react' import { z } from 'zod' import type { WidgetConfig } from './widget_config.types' -import type React from 'react'; export interface ModuleConfig { provider?: React.LazyExoticComponent< diff --git a/packages/configs/src/vite/module-vite.config.ts b/packages/configs/src/vite/module-vite.config.ts index 1c1fa041b..449cb2a19 100644 --- a/packages/configs/src/vite/module-vite.config.ts +++ b/packages/configs/src/vite/module-vite.config.ts @@ -72,7 +72,7 @@ export function defineModuleConfig( i18next: { generate: false }, '@tanstack/react-query': { generate: false }, 'react-router': { generate: false }, - 'nuqs': { generate: false }, + nuqs: { generate: false }, ...Object.fromEntries( Object.keys(SHARED_PACKAGES).map(e => [e, { generate: false }]) ) diff --git a/packages/federation/src/index.ts b/packages/federation/src/index.ts index 3b1e88d73..175d80bd5 100644 --- a/packages/federation/src/index.ts +++ b/packages/federation/src/index.ts @@ -29,5 +29,3 @@ export { fetchCategoryOrder, type CategoryOrder } from './utils/sortRoutes' - - diff --git a/packages/federation/src/loaders/loadModules.ts b/packages/federation/src/loaders/loadModules.ts index 0e9a1469a..acfef0f2b 100644 --- a/packages/federation/src/loaders/loadModules.ts +++ b/packages/federation/src/loaders/loadModules.ts @@ -1,7 +1,5 @@ -import type { - ModuleCategory, - ModuleConfig -} from '@lifeforge/configs' +import type { ModuleCategory, ModuleConfig } from '@lifeforge/configs' + import { type CategoryOrder, fetchCategoryOrder, diff --git a/packages/federation/src/utils/sortRoutes.ts b/packages/federation/src/utils/sortRoutes.ts index a178d2f0b..bb37eb7a1 100644 --- a/packages/federation/src/utils/sortRoutes.ts +++ b/packages/federation/src/utils/sortRoutes.ts @@ -1,4 +1,5 @@ import type { ModuleCategory } from '@lifeforge/configs' + import { SYSTEM_CATEGORIES } from '../providers/FederationProvider' export type CategoryOrder = Record> diff --git a/packages/log/tsconfig.json b/packages/log/tsconfig.json index a5b0da39a..5ccc72e3b 100644 --- a/packages/log/tsconfig.json +++ b/packages/log/tsconfig.json @@ -12,17 +12,9 @@ "outDir": "./dist", "rootDir": "./src", "paths": { - "@/*": [ - "./src/*" - ] + "@/*": ["./src/*"] } }, - "include": [ - "src/**/*" - ], - "exclude": [ - "node_modules", - "dist", - "**/*.test.ts" - ] -} \ No newline at end of file + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "**/*.test.ts"] +} diff --git a/packages/server-utils/src/index.ts b/packages/server-utils/src/index.ts index ebbbf9635..c0696dd06 100644 --- a/packages/server-utils/src/index.ts +++ b/packages/server-utils/src/index.ts @@ -116,4 +116,3 @@ export { type Route, type RouteStackLayer } from './routes/traceRouteStack' - diff --git a/packages/server-utils/src/typescript/core/core_context.types.ts b/packages/server-utils/src/typescript/core/core_context.types.ts index ab8ebe105..03406bfe5 100644 --- a/packages/server-utils/src/typescript/core/core_context.types.ts +++ b/packages/server-utils/src/typescript/core/core_context.types.ts @@ -12,7 +12,7 @@ import { ITempFileManagerConstructor } from './tempfile_manager.types' export type FetchAIFunc = < T extends z.ZodTypeAny | undefined = undefined >(params: { - pb: IPBService + pb: IPBService provider: string model: string messages: OpenAI.ChatCompletionMessageParam[] @@ -38,7 +38,7 @@ type CheckExistenceFunc = ( type GetAPIKeyFunc = ( id: string, - pb: IPBService + pb: IPBService ) => Promise type CheckModulesAvailabilityFunc = (moduleIds: string) => Promise @@ -92,7 +92,7 @@ export type EncryptFunc = (data: Buffer, key: string) => Buffer export type Encrypt2Func = (data: string, key: string) => string export type ValidateOTPFunc = ( - pb: IPBService, + pb: IPBService, { otp, otpId diff --git a/packages/server-utils/tsconfig.json b/packages/server-utils/tsconfig.json index beca8b32f..d7280a81f 100644 --- a/packages/server-utils/tsconfig.json +++ b/packages/server-utils/tsconfig.json @@ -3,9 +3,7 @@ "target": "ESNext", "module": "ESNext", "moduleResolution": "bundler", - "lib": [ - "ESNext" - ], + "lib": ["ESNext"], "strict": true, "esModuleInterop": true, "skipLibCheck": true, @@ -17,15 +15,8 @@ "isolatedModules": true, "noEmit": false, "emitDeclarationOnly": true, - "types": [ - "Multer" - ] + "types": ["Multer"] }, - "include": [ - "src/**/*" - ], - "exclude": [ - "node_modules", - "dist" - ] -} \ No newline at end of file + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/ui/src/components/auth/WithMasterPassword/components/CreatePasswordScreen.tsx b/packages/ui/src/components/auth/WithMasterPassword/components/CreatePasswordScreen.tsx index 5ab8c4e0d..ffb2fcea6 100644 --- a/packages/ui/src/components/auth/WithMasterPassword/components/CreatePasswordScreen.tsx +++ b/packages/ui/src/components/auth/WithMasterPassword/components/CreatePasswordScreen.tsx @@ -1,7 +1,6 @@ import { useMutation } from '@tanstack/react-query' import { useState } from 'react' import { useTranslation } from 'react-i18next' -import { toast } from '@/providers' import { encrypt } from '@lifeforge/api' import type { ForgeEndpoint } from '@lifeforge/api' @@ -9,7 +8,7 @@ import type { ForgeEndpoint } from '@lifeforge/api' import { Button, TextInput } from '@/components/inputs' import { ConfirmationModal } from '@/components/overlays' import { Box, Flex, Icon, Text } from '@/components/primitives' -import { useModalStore } from '@/providers' +import { toast, useModalStore } from '@/providers' export function CreatePasswordScreen({ controller, diff --git a/packages/ui/src/components/auth/WithMasterPassword/components/LockedScreen.tsx b/packages/ui/src/components/auth/WithMasterPassword/components/LockedScreen.tsx index 7b4e3171a..37110d164 100644 --- a/packages/ui/src/components/auth/WithMasterPassword/components/LockedScreen.tsx +++ b/packages/ui/src/components/auth/WithMasterPassword/components/LockedScreen.tsx @@ -1,13 +1,12 @@ import React, { useState } from 'react' import { useTranslation } from 'react-i18next' -import { toast } from '@/providers' -import { usePromiseLoading } from '@lifeforge/api' -import { encrypt } from '@lifeforge/api' +import { encrypt, usePromiseLoading } from '@lifeforge/api' import type { ForgeEndpoint } from '@lifeforge/api' import { Button, TextInput } from '@/components/inputs' import { Box, Flex, Icon, Text } from '@/components/primitives' +import { toast } from '@/providers' export function LockedScreen({ challengeController, diff --git a/packages/ui/src/components/form/components/FormModal/index.tsx b/packages/ui/src/components/form/components/FormModal/index.tsx index 9533f814b..04ae31f0c 100644 --- a/packages/ui/src/components/form/components/FormModal/index.tsx +++ b/packages/ui/src/components/form/components/FormModal/index.tsx @@ -1,6 +1,5 @@ import { createContext, useContext } from 'react' import { type FieldValues, type UseFormReturn } from 'react-hook-form' -import { toast } from '@/providers' import { usePromiseLoading } from '@lifeforge/api' @@ -8,6 +7,7 @@ import { LoadingScreen } from '@/components/feedback' import { Button } from '@/components/inputs' import { ModalHeader } from '@/components/overlays' import { Flex, Stack } from '@/components/primitives' +import { toast } from '@/providers' const NamespaceContext = createContext(undefined) diff --git a/packages/ui/src/components/inputs/FileInput/FilePickerModal/components/AIImageGenerator.tsx b/packages/ui/src/components/inputs/FileInput/FilePickerModal/components/AIImageGenerator.tsx index 9deebe9b2..8cc466271 100644 --- a/packages/ui/src/components/inputs/FileInput/FilePickerModal/components/AIImageGenerator.tsx +++ b/packages/ui/src/components/inputs/FileInput/FilePickerModal/components/AIImageGenerator.tsx @@ -1,13 +1,12 @@ import { useEffect, useState } from 'react' -import { toast } from '@/providers' -import { usePromiseLoading } from '@lifeforge/api' -import { useAPIEndpoint } from '@lifeforge/api' +import { useAPIEndpoint, usePromiseLoading } from '@lifeforge/api' import { EmptyStateScreen } from '@/components/feedback' import { Button, TextAreaInput } from '@/components/inputs' import { Box, Flex } from '@/components/primitives' import { WithQueryData } from '@/components/utilities' +import { toast } from '@/providers' import { forgeAPI } from '@/utils/forgeAPI' export function AIImageGenerator({ diff --git a/packages/ui/src/components/inputs/FileInput/FilePickerModal/components/LocalUpload/components/PreviewContainer.tsx b/packages/ui/src/components/inputs/FileInput/FilePickerModal/components/LocalUpload/components/PreviewContainer.tsx index e48a90e95..edf145c65 100644 --- a/packages/ui/src/components/inputs/FileInput/FilePickerModal/components/LocalUpload/components/PreviewContainer.tsx +++ b/packages/ui/src/components/inputs/FileInput/FilePickerModal/components/LocalUpload/components/PreviewContainer.tsx @@ -2,6 +2,7 @@ import { useMemo } from 'react' import { Button } from '@/components/inputs' import { Box, Flex, Icon, Text } from '@/components/primitives' + import { FILE_ICONS } from '../../../constants/file_icons' export function PreviewContainer({ diff --git a/packages/ui/src/components/inputs/FileInput/FilePickerModal/components/LocalUpload/index.tsx b/packages/ui/src/components/inputs/FileInput/FilePickerModal/components/LocalUpload/index.tsx index 7bea15256..e62f3ea2a 100644 --- a/packages/ui/src/components/inputs/FileInput/FilePickerModal/components/LocalUpload/index.tsx +++ b/packages/ui/src/components/inputs/FileInput/FilePickerModal/components/LocalUpload/index.tsx @@ -1,6 +1,7 @@ import { parse } from 'file-type-mime' import { useCallback } from 'react' import { useDropzone } from 'react-dropzone' + import { toast } from '@/providers' import { DnDContainer } from './components/DnDContainer' diff --git a/packages/ui/src/components/inputs/FileInput/FilePickerModal/components/Pixabay/index.tsx b/packages/ui/src/components/inputs/FileInput/FilePickerModal/components/Pixabay/index.tsx index 04fc90138..f023abc47 100644 --- a/packages/ui/src/components/inputs/FileInput/FilePickerModal/components/Pixabay/index.tsx +++ b/packages/ui/src/components/inputs/FileInput/FilePickerModal/components/Pixabay/index.tsx @@ -1,8 +1,6 @@ import { useReducer, useState } from 'react' -import { toast } from '@/providers' -import { usePromiseLoading } from '@lifeforge/api' -import { useAPIEndpoint } from '@lifeforge/api' +import { useAPIEndpoint, usePromiseLoading } from '@lifeforge/api' import { EmptyStateScreen, @@ -12,6 +10,7 @@ import { import { Button, SearchInput } from '@/components/inputs' import { Flex } from '@/components/primitives' import { WithQueryData } from '@/components/utilities' +import { toast } from '@/providers' import { forgeAPI } from '@/utils/forgeAPI' import { SearchFilterModal } from './components/SearchFilterModal' diff --git a/packages/ui/src/components/inputs/IconInput/IconPickerModal/pages/IconSetList/components/CategoryEntry.tsx b/packages/ui/src/components/inputs/IconInput/IconPickerModal/pages/IconSetList/components/CategoryEntry.tsx index 9a4e32992..d19ef7a65 100644 --- a/packages/ui/src/components/inputs/IconInput/IconPickerModal/pages/IconSetList/components/CategoryEntry.tsx +++ b/packages/ui/src/components/inputs/IconInput/IconPickerModal/pages/IconSetList/components/CategoryEntry.tsx @@ -2,8 +2,8 @@ import { memo } from 'react' import { Bordered, Box, Grid, Text } from '@/components/primitives' -import { IconSetEntry } from './IconSetEntry' import type { IIconSet } from '../../../typescript/icon_selector_interfaces' +import { IconSetEntry } from './IconSetEntry' function _CategoryEntry({ category, diff --git a/packages/ui/src/components/inputs/IconInput/IconPickerModal/pages/IconSetList/components/IconSetEntry.tsx b/packages/ui/src/components/inputs/IconInput/IconPickerModal/pages/IconSetList/components/IconSetEntry.tsx index 60344dc0f..ac8552025 100644 --- a/packages/ui/src/components/inputs/IconInput/IconPickerModal/pages/IconSetList/components/IconSetEntry.tsx +++ b/packages/ui/src/components/inputs/IconInput/IconPickerModal/pages/IconSetList/components/IconSetEntry.tsx @@ -2,6 +2,7 @@ import { memo, useCallback } from 'react' import { Card } from '@/components/layout' import { Bordered, Box, Flex, Icon, Text } from '@/components/primitives' + import type { IIconSet } from '../../../typescript/icon_selector_interfaces' function _IconSetEntry({ diff --git a/packages/ui/src/components/inputs/shared/components/InputLabel/index.tsx b/packages/ui/src/components/inputs/shared/components/InputLabel/index.tsx index bba1cf2e0..9c3024a86 100644 --- a/packages/ui/src/components/inputs/shared/components/InputLabel/index.tsx +++ b/packages/ui/src/components/inputs/shared/components/InputLabel/index.tsx @@ -3,11 +3,11 @@ import { type CSSProperties, memo } from 'react' import { Flex, Icon, Text, Transition } from '@/components/primitives' +import { useInputFocused } from '../../contexts/InputFocusContext' import { inputLabelActiveStyle, inputLabelInactiveStyle } from './InputLabel.css' -import { useInputFocused } from '../../contexts/InputFocusContext' interface InputLabelProps { label: string diff --git a/packages/ui/src/components/layout/ModuleHeader/index.tsx b/packages/ui/src/components/layout/ModuleHeader/index.tsx index ab7bebb18..fca1a58e4 100644 --- a/packages/ui/src/components/layout/ModuleHeader/index.tsx +++ b/packages/ui/src/components/layout/ModuleHeader/index.tsx @@ -1,13 +1,12 @@ import { Menu, MenuButton, MenuItems } from '@headlessui/react' import { useTranslation } from 'react-i18next' -import { useMainSidebarState } from '../../../providers' - import { Button } from '@/components/inputs' import { Box, Flex, Icon, Text, Transition } from '@/components/primitives' import { useModuleHeaderState } from '@/providers' import { colorWithOpacity } from '@/system' +import { useMainSidebarState } from '../../../providers' import { ContextMenu } from '../../overlays/ContextMenu' interface ModuleHeaderProps { diff --git a/packages/ui/src/components/navigation/sidebar/SidebarItem/components/SidebarSubsectionItemLink.tsx b/packages/ui/src/components/navigation/sidebar/SidebarItem/components/SidebarSubsectionItemLink.tsx index caeb9ce0f..207c2fd63 100644 --- a/packages/ui/src/components/navigation/sidebar/SidebarItem/components/SidebarSubsectionItemLink.tsx +++ b/packages/ui/src/components/navigation/sidebar/SidebarItem/components/SidebarSubsectionItemLink.tsx @@ -1,12 +1,11 @@ import _ from 'lodash' import { useCallback, useMemo } from 'react' import { useTranslation } from 'react-i18next' - +import { Link, useLocation } from 'react-router' import { Flex, Icon, Text, Transition } from '@/components/primitives' import { useMainSidebarState } from '@/providers' import { colorWithOpacity } from '@/system/colors/color-with-opacity' -import { Link, useLocation } from 'react-router' export function SidebarSubsectionItemLink({ subsectionLabel, diff --git a/packages/ui/src/contract.ts b/packages/ui/src/contract.ts index 528328417..4dbb4bc79 100644 --- a/packages/ui/src/contract.ts +++ b/packages/ui/src/contract.ts @@ -1,2982 +1,2782 @@ export const contract = { - "": { - "method": "get", - "description": "Welcome to LifeForge API", - "noAuth": true, - "encrypted": false, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string", - "const": "Get ready to forge your life!" + '': { + method: 'get', + description: 'Welcome to LifeForge API', + noAuth: true, + encrypted: false, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string', + const: 'Get ready to forge your life!' } } }, - "locales": { - "listLanguages": { - "method": "get", - "description": "List all languages", - "noAuth": true, - "encrypted": false, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" + locales: { + listLanguages: { + method: 'get', + description: 'List all languages', + noAuth: true, + encrypted: false, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string' }, - "alternative": { - "type": "array", - "items": { - "type": "string" + alternative: { + type: 'array', + items: { + type: 'string' } }, - "icon": { - "type": "string" + icon: { + type: 'string' }, - "displayName": { - "type": "string" + displayName: { + type: 'string' } }, - "required": [ - "name", - "icon", - "displayName" - ], - "additionalProperties": false + required: ['name', 'icon', 'displayName'], + additionalProperties: false } } } }, - "getLocale": { - "method": "get", - "description": "Retrieve localization strings for namespace", - "noAuth": true, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "lang": { - "type": "string" + getLocale: { + method: 'get', + description: 'Retrieve localization strings for namespace', + noAuth: true, + encrypted: true, + isDownloadable: false, + media: null, + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + lang: { + type: 'string' }, - "namespace": { - "type": "string", - "enum": [ - "apps", - "common" - ] + namespace: { + type: 'string', + enum: ['apps', 'common'] }, - "subnamespace": { - "type": "string" + subnamespace: { + type: 'string' } }, - "required": [ - "lang", - "namespace", - "subnamespace" - ], - "additionalProperties": false + required: ['lang', 'namespace', 'subnamespace'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "additionalProperties": {} + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + additionalProperties: {} }, - "NOT_FOUND": true + NOT_FOUND: true } }, - "notifyMissing": { - "method": "post", - "description": "Report missing localization key", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "namespace": { - "type": "string" + notifyMissing: { + method: 'post', + description: 'Report missing localization key', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + namespace: { + type: 'string' }, - "key": { - "type": "string" + key: { + type: 'string' } }, - "required": [ - "namespace", - "key" - ], - "additionalProperties": false + required: ['namespace', 'key'], + additionalProperties: false } }, - "output": { - "NO_CONTENT": true + output: { + NO_CONTENT: true } } }, - "user": { - "exists": { - "method": "get", - "description": "Check if user exists", - "noAuth": true, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "boolean" + user: { + exists: { + method: 'get', + description: 'Check if user exists', + noAuth: true, + encrypted: true, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'boolean' } } }, - "auth": { - "createFirstUser": { - "method": "post", - "description": "Create the first user (only works when no users exist)", - "noAuth": true, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "email", - "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" + auth: { + createFirstUser: { + method: 'post', + description: 'Create the first user (only works when no users exist)', + noAuth: true, + encrypted: true, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + email: { + type: 'string', + format: 'email', + pattern: + "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" }, - "username": { - "type": "string", - "minLength": 3 + username: { + type: 'string', + minLength: 3 }, - "name": { - "type": "string", - "minLength": 1 + name: { + type: 'string', + minLength: 1 }, - "password": { - "type": "string", - "minLength": 8 + password: { + type: 'string', + minLength: 8 } }, - "required": [ - "email", - "username", - "name", - "password" - ], - "additionalProperties": false + required: ['email', 'username', 'name', 'password'], + additionalProperties: false } }, - "output": { - "CREATED": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "state": { - "type": "string", - "const": "success" + output: { + CREATED: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + state: { + type: 'string', + const: 'success' } }, - "required": [ - "state" - ], - "additionalProperties": false + required: ['state'], + additionalProperties: false }, - "BAD_REQUEST": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + BAD_REQUEST: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' } } }, - "generateOTP": { - "method": "get", - "description": "Generate one-time password", - "noAuth": false, - "encrypted": false, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + generateOTP: { + method: 'get', + description: 'Generate one-time password', + noAuth: false, + encrypted: false, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' } } }, - "getUserData": { - "method": "get", - "description": "Get current user data", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "email", - "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" + getUserData: { + method: 'get', + description: 'Get current user data', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + email: { + type: 'string', + format: 'email', + pattern: + "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" }, - "emailVisibility": { - "type": "boolean" + emailVisibility: { + type: 'boolean' }, - "verified": { - "type": "boolean" + verified: { + type: 'boolean' }, - "username": { - "type": "string" + username: { + type: 'string' }, - "name": { - "type": "string" + name: { + type: 'string' }, - "avatar": { - "type": "string" + avatar: { + type: 'string' }, - "dateOfBirth": { - "type": "string" + dateOfBirth: { + type: 'string' }, - "theme": { - "type": "string", - "enum": [ - "system", - "light", - "dark" - ] + theme: { + type: 'string', + enum: ['system', 'light', 'dark'] }, - "color": { - "type": "string" + color: { + type: 'string' }, - "bgTemp": { - "type": "string" + bgTemp: { + type: 'string' }, - "bgImage": { - "type": "string" + bgImage: { + type: 'string' }, - "backdropFilters": {}, - "fontFamily": { - "type": "string" + backdropFilters: {}, + fontFamily: { + type: 'string' }, - "language": { - "type": "string" + language: { + type: 'string' }, - "dashboardLayout": {}, - "fontScale": { - "type": "number" + dashboardLayout: {}, + fontScale: { + type: 'number' }, - "pinnedFontFamilies": {}, - "borderRadiusMultiplier": { - "type": "number" + pinnedFontFamilies: {}, + borderRadiusMultiplier: { + type: 'number' }, - "bordered": { - "type": "boolean" + bordered: { + type: 'boolean' }, - "created": { - "type": "string" + created: { + type: 'string' }, - "updated": { - "type": "string" + updated: { + type: 'string' }, - "id": { - "type": "string" + id: { + type: 'string' }, - "collectionId": { - "type": "string" + collectionId: { + type: 'string' }, - "collectionName": { - "type": "string" + collectionName: { + type: 'string' }, - "hasMasterPassword": { - "type": "boolean" + hasMasterPassword: { + type: 'boolean' }, - "hasJournalMasterPassword": { - "type": "boolean" + hasJournalMasterPassword: { + type: 'boolean' }, - "hasAPIKeysMasterPassword": { - "type": "boolean" + hasAPIKeysMasterPassword: { + type: 'boolean' }, - "twoFAEnabled": { - "type": "boolean" + twoFAEnabled: { + type: 'boolean' } }, - "required": [ - "email", - "emailVisibility", - "verified", - "username", - "name", - "avatar", - "dateOfBirth", - "theme", - "color", - "bgTemp", - "bgImage", - "backdropFilters", - "fontFamily", - "language", - "dashboardLayout", - "fontScale", - "pinnedFontFamilies", - "borderRadiusMultiplier", - "bordered", - "created", - "updated", - "id", - "collectionId", - "collectionName", - "hasMasterPassword", - "hasJournalMasterPassword", - "hasAPIKeysMasterPassword", - "twoFAEnabled" + required: [ + 'email', + 'emailVisibility', + 'verified', + 'username', + 'name', + 'avatar', + 'dateOfBirth', + 'theme', + 'color', + 'bgTemp', + 'bgImage', + 'backdropFilters', + 'fontFamily', + 'language', + 'dashboardLayout', + 'fontScale', + 'pinnedFontFamilies', + 'borderRadiusMultiplier', + 'bordered', + 'created', + 'updated', + 'id', + 'collectionId', + 'collectionName', + 'hasMasterPassword', + 'hasJournalMasterPassword', + 'hasAPIKeysMasterPassword', + 'twoFAEnabled' ], - "additionalProperties": false + additionalProperties: false }, - "NOT_FOUND": true + NOT_FOUND: true } }, - "login": { - "method": "post", - "description": "Authenticate user with credentials", - "noAuth": true, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "email": { - "type": "string" + login: { + method: 'post', + description: 'Authenticate user with credentials', + noAuth: true, + encrypted: true, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + email: { + type: 'string' }, - "password": { - "type": "string" + password: { + type: 'string' } }, - "required": [ - "email", - "password" - ], - "additionalProperties": false + required: ['email', 'password'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "anyOf": [ + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + anyOf: [ { - "type": "object", - "properties": { - "state": { - "type": "string", - "const": "2fa_required" + type: 'object', + properties: { + state: { + type: 'string', + const: '2fa_required' }, - "tid": { - "type": "string" + tid: { + type: 'string' } }, - "required": [ - "state", - "tid" - ], - "additionalProperties": false + required: ['state', 'tid'], + additionalProperties: false }, { - "type": "object", - "properties": { - "state": { - "type": "string", - "const": "success" + type: 'object', + properties: { + state: { + type: 'string', + const: 'success' }, - "session": { - "type": "string" + session: { + type: 'string' } }, - "required": [ - "state", - "session" - ], - "additionalProperties": false + required: ['state', 'session'], + additionalProperties: false } ] }, - "UNAUTHORIZED": true + UNAUTHORIZED: true } }, - "validateOTP": { - "method": "post", - "description": "Verify one-time password", - "noAuth": false, - "encrypted": false, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "otp": { - "type": "string" + validateOTP: { + method: 'post', + description: 'Verify one-time password', + noAuth: false, + encrypted: false, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + otp: { + type: 'string' }, - "otpId": { - "type": "string" + otpId: { + type: 'string' } }, - "required": [ - "otp", - "otpId" - ], - "additionalProperties": false + required: ['otp', 'otpId'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "boolean" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'boolean' } } }, - "verifySessionToken": { - "method": "post", - "description": "Validate user session token", - "noAuth": false, - "encrypted": false, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "boolean" + verifySessionToken: { + method: 'post', + description: 'Validate user session token', + noAuth: false, + encrypted: false, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'boolean' }, - "UNAUTHORIZED": true + UNAUTHORIZED: true } } }, - "oauth": { - "getEndpoint": { - "method": "get", - "description": "Get OAuth authorization URL for provider", - "noAuth": true, - "encrypted": false, - "isDownloadable": false, - "media": null, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "provider": { - "type": "string" + oauth: { + getEndpoint: { + method: 'get', + description: 'Get OAuth authorization URL for provider', + noAuth: true, + encrypted: false, + isDownloadable: false, + media: null, + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + provider: { + type: 'string' } }, - "required": [ - "provider" - ], - "additionalProperties": false + required: ['provider'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "name": { - "type": "string" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + name: { + type: 'string' }, - "state": { - "type": "string" + state: { + type: 'string' }, - "codeVerifier": { - "type": "string" + codeVerifier: { + type: 'string' }, - "codeChallenge": { - "type": "string" + codeChallenge: { + type: 'string' }, - "codeChallengeMethod": { - "type": "string" + codeChallengeMethod: { + type: 'string' }, - "authURL": { - "type": "string" + authURL: { + type: 'string' }, - "displayName": { - "type": "string" + displayName: { + type: 'string' } }, - "required": [ - "name", - "state", - "codeVerifier", - "codeChallenge", - "codeChallengeMethod", - "authURL", - "displayName" + required: [ + 'name', + 'state', + 'codeVerifier', + 'codeChallenge', + 'codeChallengeMethod', + 'authURL', + 'displayName' ], - "additionalProperties": false + additionalProperties: false }, - "BAD_REQUEST": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + BAD_REQUEST: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' } } }, - "listProviders": { - "method": "get", - "description": "Retrieve available OAuth providers", - "noAuth": true, - "encrypted": false, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "array", - "items": { - "type": "string" + listProviders: { + method: 'get', + description: 'Retrieve available OAuth providers', + noAuth: true, + encrypted: false, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'array', + items: { + type: 'string' } } } }, - "verify": { - "method": "post", - "description": "Verify OAuth authorization callback", - "noAuth": true, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "provider": { - "type": "string" + verify: { + method: 'post', + description: 'Verify OAuth authorization callback', + noAuth: true, + encrypted: true, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + provider: { + type: 'string' }, - "code": { - "type": "string" + code: { + type: 'string' } }, - "required": [ - "provider", - "code" - ], - "additionalProperties": false + required: ['provider', 'code'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "anyOf": [ + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + anyOf: [ { - "type": "object", - "properties": { - "state": { - "type": "string", - "const": "2fa_required" + type: 'object', + properties: { + state: { + type: 'string', + const: '2fa_required' }, - "tid": { - "type": "string" + tid: { + type: 'string' } }, - "required": [ - "state", - "tid" - ], - "additionalProperties": false + required: ['state', 'tid'], + additionalProperties: false }, { - "type": "string" + type: 'string' } ] }, - "UNAUTHORIZED": true, - "BAD_REQUEST": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + UNAUTHORIZED: true, + BAD_REQUEST: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' } } } }, - "2fa": { - "disable": { - "method": "post", - "description": "Disable two-factor authentication", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "NO_CONTENT": true + '2fa': { + disable: { + method: 'post', + description: 'Disable two-factor authentication', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: {}, + output: { + NO_CONTENT: true } }, - "generateAuthenticatorLink": { - "method": "get", - "description": "Generate authenticator app setup link", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + generateAuthenticatorLink: { + method: 'get', + description: 'Generate authenticator app setup link', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' } } }, - "getChallenge": { - "method": "get", - "description": "Retrieve 2FA challenge token", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + getChallenge: { + method: 'get', + description: 'Retrieve 2FA challenge token', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' } } }, - "requestOTP": { - "method": "get", - "description": "Request OTP for two-factor authentication", - "noAuth": true, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "email", - "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" + requestOTP: { + method: 'get', + description: 'Request OTP for two-factor authentication', + noAuth: true, + encrypted: true, + isDownloadable: false, + media: null, + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + email: { + type: 'string', + format: 'email', + pattern: + "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" } }, - "required": [ - "email" - ], - "additionalProperties": false + required: ['email'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' }, - "BAD_REQUEST": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + BAD_REQUEST: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' } } }, - "verify": { - "method": "post", - "description": "Verify two-factor authentication code", - "noAuth": true, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "otp": { - "type": "string" + verify: { + method: 'post', + description: 'Verify two-factor authentication code', + noAuth: true, + encrypted: true, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + otp: { + type: 'string' }, - "tid": { - "type": "string" + tid: { + type: 'string' }, - "type": { - "type": "string", - "enum": [ - "email", - "app" - ] + type: { + type: 'string', + enum: ['email', 'app'] } }, - "required": [ - "otp", - "tid", - "type" - ], - "additionalProperties": false + required: ['otp', 'tid', 'type'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "session": { - "type": "string" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + session: { + type: 'string' } }, - "required": [ - "session" - ], - "additionalProperties": false + required: ['session'], + additionalProperties: false }, - "UNAUTHORIZED": true + UNAUTHORIZED: true } }, - "verifyAndEnable": { - "method": "post", - "description": "Verify and activate two-factor authentication", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "otp": { - "type": "string" + verifyAndEnable: { + method: 'post', + description: 'Verify and activate two-factor authentication', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + otp: { + type: 'string' } }, - "required": [ - "otp" - ], - "additionalProperties": false + required: ['otp'], + additionalProperties: false } }, - "output": { - "NO_CONTENT": true, - "UNAUTHORIZED": true + output: { + NO_CONTENT: true, + UNAUTHORIZED: true } } }, - "qrLogin": { - "approveQRLogin": { - "method": "post", - "description": "Approve a QR login request", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "sessionId": { - "type": "string", - "format": "uuid", - "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" + qrLogin: { + approveQRLogin: { + method: 'post', + description: 'Approve a QR login request', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + sessionId: { + type: 'string', + format: 'uuid', + pattern: + '^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$' } }, - "required": [ - "sessionId" - ], - "additionalProperties": false + required: ['sessionId'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "success": { - "type": "boolean" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + success: { + type: 'boolean' }, - "browserInfo": { - "type": "string" + browserInfo: { + type: 'string' } }, - "required": [ - "success", - "browserInfo" - ], - "additionalProperties": false + required: ['success', 'browserInfo'], + additionalProperties: false }, - "NOT_FOUND": true, - "BAD_REQUEST": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + NOT_FOUND: true, + BAD_REQUEST: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' } } }, - "checkQRSessionStatus": { - "method": "get", - "description": "Check QR login session status", - "noAuth": true, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "sessionId": { - "type": "string", - "format": "uuid", - "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" + checkQRSessionStatus: { + method: 'get', + description: 'Check QR login session status', + noAuth: true, + encrypted: true, + isDownloadable: false, + media: null, + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + sessionId: { + type: 'string', + format: 'uuid', + pattern: + '^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$' } }, - "required": [ - "sessionId" - ], - "additionalProperties": false + required: ['sessionId'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "anyOf": [ + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + anyOf: [ { - "type": "object", - "properties": { - "status": { - "type": "string", - "const": "not_found" + type: 'object', + properties: { + status: { + type: 'string', + const: 'not_found' } }, - "required": [ - "status" - ], - "additionalProperties": false + required: ['status'], + additionalProperties: false }, { - "type": "object", - "properties": { - "status": { - "type": "string", - "const": "expired" + type: 'object', + properties: { + status: { + type: 'string', + const: 'expired' } }, - "required": [ - "status" - ], - "additionalProperties": false + required: ['status'], + additionalProperties: false }, { - "type": "object", - "properties": { - "status": { - "type": "string", - "const": "approved" + type: 'object', + properties: { + status: { + type: 'string', + const: 'approved' }, - "session": { - "type": "string" + session: { + type: 'string' } }, - "required": [ - "status", - "session" - ], - "additionalProperties": false + required: ['status', 'session'], + additionalProperties: false }, { - "type": "object", - "properties": { - "status": { - "type": "string", - "const": "pending" + type: 'object', + properties: { + status: { + type: 'string', + const: 'pending' }, - "expiresAt": { - "type": "string" + expiresAt: { + type: 'string' } }, - "required": [ - "status", - "expiresAt" - ], - "additionalProperties": false + required: ['status', 'expiresAt'], + additionalProperties: false } ] } } }, - "registerQRSession": { - "method": "post", - "description": "Register a new QR login session", - "noAuth": true, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "sessionId": { - "type": "string", - "format": "uuid", - "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" + registerQRSession: { + method: 'post', + description: 'Register a new QR login session', + noAuth: true, + encrypted: true, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + sessionId: { + type: 'string', + format: 'uuid', + pattern: + '^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$' }, - "browserInfo": { - "type": "string" + browserInfo: { + type: 'string' } }, - "required": [ - "sessionId", - "browserInfo" - ], - "additionalProperties": false + required: ['sessionId', 'browserInfo'], + additionalProperties: false } }, - "output": { - "CREATED": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "sessionId": { - "type": "string" + output: { + CREATED: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + sessionId: { + type: 'string' }, - "expiresAt": { - "type": "string" + expiresAt: { + type: 'string' } }, - "required": [ - "sessionId", - "expiresAt" - ], - "additionalProperties": false + required: ['sessionId', 'expiresAt'], + additionalProperties: false }, - "BAD_REQUEST": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + BAD_REQUEST: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' } } } }, - "settings": { - "deleteAvatar": { - "method": "post", - "description": "Remove user avatar", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "NO_CONTENT": true + settings: { + deleteAvatar: { + method: 'post', + description: 'Remove user avatar', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: {}, + output: { + NO_CONTENT: true } }, - "requestPasswordReset": { - "method": "post", - "description": "Request password reset email", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "NO_CONTENT": true + requestPasswordReset: { + method: 'post', + description: 'Request password reset email', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: {}, + output: { + NO_CONTENT: true } }, - "updateAvatar": { - "method": "post", - "description": "Upload new user avatar", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": { - "file": { - "optional": false + updateAvatar: { + method: 'post', + description: 'Upload new user avatar', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: { + file: { + optional: false } }, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' } } }, - "updateProfile": { - "method": "post", - "description": "Update user profile information", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "data": { - "type": "object", - "properties": { - "username": { - "type": "string", - "pattern": "^[a-zA-Z0-9]+$" + updateProfile: { + method: 'post', + description: 'Update user profile information', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + data: { + type: 'object', + properties: { + username: { + type: 'string', + pattern: '^[a-zA-Z0-9]+$' }, - "email": { - "type": "string", - "format": "email", - "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" + email: { + type: 'string', + format: 'email', + pattern: + "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" }, - "name": { - "type": "string" + name: { + type: 'string' }, - "dateOfBirth": { - "type": "string" + dateOfBirth: { + type: 'string' } }, - "additionalProperties": false + additionalProperties: false } }, - "required": [ - "data" - ], - "additionalProperties": false + required: ['data'], + additionalProperties: false } }, - "output": { - "NO_CONTENT": true + output: { + NO_CONTENT: true } } }, - "personalization": { - "deleteBgImage": { - "method": "post", - "description": "Remove background image", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "NO_CONTENT": true + personalization: { + deleteBgImage: { + method: 'post', + description: 'Remove background image', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: {}, + output: { + NO_CONTENT: true } }, - "getGoogleFont": { - "method": "get", - "description": "Get details of a specific Google Font", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "family": { - "type": "string" + getGoogleFont: { + method: 'get', + description: 'Get details of a specific Google Font', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + family: { + type: 'string' } }, - "required": [ - "family" - ], - "additionalProperties": false + required: ['family'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "enabled": { - "type": "boolean" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + enabled: { + type: 'boolean' }, - "items": {} + items: {} }, - "required": [ - "enabled" - ], - "additionalProperties": false + required: ['enabled'], + additionalProperties: false } } }, - "listGoogleFonts": { - "method": "get", - "description": "Retrieve available Google Fonts", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "enabled": { - "type": "boolean" + listGoogleFonts: { + method: 'get', + description: 'Retrieve available Google Fonts', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + enabled: { + type: 'boolean' }, - "items": { - "type": "array", - "items": { - "type": "object", - "properties": { - "family": { - "type": "string" + items: { + type: 'array', + items: { + type: 'object', + properties: { + family: { + type: 'string' }, - "variants": { - "type": "array", - "items": { - "type": "string" + variants: { + type: 'array', + items: { + type: 'string' } }, - "subsets": { - "type": "array", - "items": { - "type": "string" + subsets: { + type: 'array', + items: { + type: 'string' } }, - "version": { - "type": "string" + version: { + type: 'string' }, - "lastModified": { - "type": "string" + lastModified: { + type: 'string' }, - "files": { - "type": "object", - "properties": { - "100": { - "type": "string" + files: { + type: 'object', + properties: { + '100': { + type: 'string' }, - "200": { - "type": "string" + '200': { + type: 'string' }, - "300": { - "type": "string" + '300': { + type: 'string' }, - "500": { - "type": "string" + '500': { + type: 'string' }, - "600": { - "type": "string" + '600': { + type: 'string' }, - "700": { - "type": "string" + '700': { + type: 'string' }, - "800": { - "type": "string" + '800': { + type: 'string' }, - "900": { - "type": "string" + '900': { + type: 'string' }, - "regular": { - "type": "string" + regular: { + type: 'string' }, - "italic": { - "type": "string" + italic: { + type: 'string' }, - "100italic": { - "type": "string" + '100italic': { + type: 'string' }, - "200italic": { - "type": "string" + '200italic': { + type: 'string' }, - "300italic": { - "type": "string" + '300italic': { + type: 'string' }, - "500italic": { - "type": "string" + '500italic': { + type: 'string' }, - "600italic": { - "type": "string" + '600italic': { + type: 'string' }, - "700italic": { - "type": "string" + '700italic': { + type: 'string' }, - "800italic": { - "type": "string" + '800italic': { + type: 'string' }, - "900italic": { - "type": "string" + '900italic': { + type: 'string' } }, - "additionalProperties": false + additionalProperties: false }, - "category": { - "type": "string", - "enum": [ - "display", - "handwriting", - "monospace", - "sans-serif", - "serif" + category: { + type: 'string', + enum: [ + 'display', + 'handwriting', + 'monospace', + 'sans-serif', + 'serif' ] }, - "kind": { - "type": "string", - "const": "webfonts#webfont" + kind: { + type: 'string', + const: 'webfonts#webfont' }, - "menu": { - "type": "string" + menu: { + type: 'string' }, - "colorCapabilities": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "COLRv0", - "COLRv1", - "SVG" - ] + colorCapabilities: { + type: 'array', + items: { + type: 'string', + enum: ['COLRv0', 'COLRv1', 'SVG'] } } }, - "required": [ - "family", - "variants", - "subsets", - "version", - "lastModified", - "files", - "category", - "kind", - "menu" + required: [ + 'family', + 'variants', + 'subsets', + 'version', + 'lastModified', + 'files', + 'category', + 'kind', + 'menu' ], - "additionalProperties": false + additionalProperties: false } } }, - "required": [ - "enabled", - "items" - ], - "additionalProperties": false + required: ['enabled', 'items'], + additionalProperties: false } } }, - "listGoogleFontsPin": { - "method": "get", - "description": "Retrieve pinned Google Fonts", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "array", - "items": { - "type": "string" + listGoogleFontsPin: { + method: 'get', + description: 'Retrieve pinned Google Fonts', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'array', + items: { + type: 'string' } }, - "UNAUTHORIZED": true + UNAUTHORIZED: true } }, - "toggleGoogleFontsPin": { - "method": "post", - "description": "Pin or unpin a Google Font", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "family": { - "type": "string" + toggleGoogleFontsPin: { + method: 'post', + description: 'Pin or unpin a Google Font', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + family: { + type: 'string' } }, - "required": [ - "family" - ], - "additionalProperties": false + required: ['family'], + additionalProperties: false } }, - "output": { - "NO_CONTENT": true, - "UNAUTHORIZED": true + output: { + NO_CONTENT: true, + UNAUTHORIZED: true } }, - "updateBgImage": { - "method": "post", - "description": "Upload new background image", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": { - "file": { - "optional": false + updateBgImage: { + method: 'post', + description: 'Upload new background image', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: { + file: { + optional: false } }, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "collectionId": { - "type": "string" + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + collectionId: { + type: 'string' }, - "recordId": { - "type": "string" + recordId: { + type: 'string' }, - "fieldId": { - "type": "string" + fieldId: { + type: 'string' } }, - "required": [ - "collectionId", - "recordId", - "fieldId" - ], - "additionalProperties": false + required: ['collectionId', 'recordId', 'fieldId'], + additionalProperties: false } } }, - "updatePersonalization": { - "method": "post", - "description": "Update user personalization preferences", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "data": { - "type": "object", - "properties": { - "fontFamily": { - "type": "string" + updatePersonalization: { + method: 'post', + description: 'Update user personalization preferences', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + data: { + type: 'object', + properties: { + fontFamily: { + type: 'string' }, - "theme": { - "type": "string" + theme: { + type: 'string' }, - "color": { - "type": "string" + color: { + type: 'string' }, - "bgTemp": { - "type": "string" + bgTemp: { + type: 'string' }, - "language": { - "type": "string" + language: { + type: 'string' }, - "fontScale": { - "type": "number" + fontScale: { + type: 'number' }, - "borderRadiusMultiplier": { - "type": "number" + borderRadiusMultiplier: { + type: 'number' }, - "bordered": { - "type": "boolean" + bordered: { + type: 'boolean' }, - "dashboardLayout": { - "type": "object", - "additionalProperties": {} + dashboardLayout: { + type: 'object', + additionalProperties: {} }, - "backdropFilters": { - "type": "object", - "additionalProperties": {} + backdropFilters: { + type: 'object', + additionalProperties: {} } }, - "additionalProperties": false + additionalProperties: false } }, - "required": [ - "data" - ], - "additionalProperties": false + required: ['data'], + additionalProperties: false } }, - "output": { - "NO_CONTENT": true, - "BAD_REQUEST": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + output: { + NO_CONTENT: true, + BAD_REQUEST: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' } } } }, - "customFonts": { - "get": { - "method": "get", - "description": "Get a specific custom font by ID", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "id": { - "type": "string" + customFonts: { + get: { + method: 'get', + description: 'Get a specific custom font by ID', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + id: { + type: 'string' } }, - "required": [ - "id" - ], - "additionalProperties": false + required: ['id'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "id": { - "type": "string" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + id: { + type: 'string' }, - "displayName": { - "type": "string" + displayName: { + type: 'string' }, - "family": { - "type": "string" + family: { + type: 'string' }, - "weight": { - "type": "number" + weight: { + type: 'number' }, - "file": { - "type": "string" + file: { + type: 'string' }, - "collectionId": { - "type": "string" + collectionId: { + type: 'string' } }, - "required": [ - "id", - "displayName", - "family", - "weight", - "file", - "collectionId" + required: [ + 'id', + 'displayName', + 'family', + 'weight', + 'file', + 'collectionId' ], - "additionalProperties": false + additionalProperties: false }, - "NOT_FOUND": true + NOT_FOUND: true } }, - "list": { - "method": "get", - "description": "List all custom uploaded fonts", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" + list: { + method: 'get', + description: 'List all custom uploaded fonts', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string' }, - "displayName": { - "type": "string" + displayName: { + type: 'string' }, - "family": { - "type": "string" + family: { + type: 'string' }, - "weight": { - "type": "number" + weight: { + type: 'number' }, - "file": { - "type": "string" + file: { + type: 'string' }, - "collectionId": { - "type": "string" + collectionId: { + type: 'string' } }, - "required": [ - "id", - "displayName", - "family", - "weight", - "file", - "collectionId" + required: [ + 'id', + 'displayName', + 'family', + 'weight', + 'file', + 'collectionId' ], - "additionalProperties": false + additionalProperties: false } } } }, - "remove": { - "method": "post", - "description": "Delete a custom font", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "id": { - "type": "string" + remove: { + method: 'post', + description: 'Delete a custom font', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + id: { + type: 'string' } }, - "required": [ - "id" - ], - "additionalProperties": false + required: ['id'], + additionalProperties: false } }, - "output": { - "NO_CONTENT": true, - "NOT_FOUND": true + output: { + NO_CONTENT: true, + NOT_FOUND: true } }, - "upload": { - "method": "post", - "description": "Upload a new custom font", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": { - "file": { - "optional": false + upload: { + method: 'post', + description: 'Upload a new custom font', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: { + file: { + optional: false } }, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "id": { - "type": "string" + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + id: { + type: 'string' } }, - "additionalProperties": false + additionalProperties: false }, - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "displayName": { - "type": "string", - "minLength": 1 + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + displayName: { + type: 'string', + minLength: 1 }, - "family": { - "type": "string", - "minLength": 1 + family: { + type: 'string', + minLength: 1 }, - "weight": { - "default": 400, - "type": "number", - "minimum": 100, - "maximum": 900 + weight: { + default: 400, + type: 'number', + minimum: 100, + maximum: 900 } }, - "required": [ - "displayName", - "family", - "weight" - ], - "additionalProperties": false + required: ['displayName', 'family', 'weight'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "id": { - "type": "string" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + id: { + type: 'string' }, - "displayName": { - "type": "string" + displayName: { + type: 'string' }, - "family": { - "type": "string" + family: { + type: 'string' }, - "weight": { - "type": "number" + weight: { + type: 'number' }, - "file": { - "type": "string" + file: { + type: 'string' }, - "collectionId": { - "type": "string" + collectionId: { + type: 'string' } }, - "required": [ - "id", - "displayName", - "family", - "weight", - "file", - "collectionId" + required: [ + 'id', + 'displayName', + 'family', + 'weight', + 'file', + 'collectionId' ], - "additionalProperties": false + additionalProperties: false }, - "BAD_REQUEST": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + BAD_REQUEST: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' }, - "NOT_FOUND": true + NOT_FOUND: true } } } }, - "apiKeys": { - "entries": { - "get": { - "method": "get", - "description": "Retrieve API key by key ID. Only exposable keys can be retrieved.", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "keyId": { - "type": "string" + apiKeys: { + entries: { + get: { + method: 'get', + description: + 'Retrieve API key by key ID. Only exposable keys can be retrieved.', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + keyId: { + type: 'string' } }, - "required": [ - "keyId" - ], - "additionalProperties": false + required: ['keyId'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "anyOf": [ + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + anyOf: [ { - "type": "string" + type: 'string' }, { - "type": "null" + type: 'null' } ] }, - "FORBIDDEN": true + FORBIDDEN: true } }, - "list": { - "method": "get", - "description": "Retrieve all API key entries", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "array", - "items": { - "type": "object", - "properties": { - "keyId": { - "type": "string" + list: { + method: 'get', + description: 'Retrieve all API key entries', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'array', + items: { + type: 'object', + properties: { + keyId: { + type: 'string' }, - "name": { - "type": "string" + name: { + type: 'string' }, - "icon": { - "type": "string" + icon: { + type: 'string' }, - "key": { - "type": "string" + key: { + type: 'string' }, - "exposable": { - "type": "boolean" + exposable: { + type: 'boolean' }, - "created": { - "type": "string" + created: { + type: 'string' }, - "updated": { - "type": "string" + updated: { + type: 'string' }, - "id": { - "type": "string" + id: { + type: 'string' }, - "collectionId": { - "type": "string" + collectionId: { + type: 'string' }, - "collectionName": { - "type": "string" + collectionName: { + type: 'string' } }, - "required": [ - "keyId", - "name", - "icon", - "key", - "exposable", - "created", - "updated", - "id", - "collectionId", - "collectionName" + required: [ + 'keyId', + 'name', + 'icon', + 'key', + 'exposable', + 'created', + 'updated', + 'id', + 'collectionId', + 'collectionName' ], - "additionalProperties": false + additionalProperties: false } } } }, - "checkKeys": { - "method": "get", - "description": "Verify if API keys exist", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "keys": { - "type": "string" + checkKeys: { + method: 'get', + description: 'Verify if API keys exist', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + keys: { + type: 'string' } }, - "required": [ - "keys" - ], - "additionalProperties": false + required: ['keys'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "boolean" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'boolean' } } }, - "create": { - "method": "post", - "description": "Create a new API key entry", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "keyId": { - "type": "string" + create: { + method: 'post', + description: 'Create a new API key entry', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + keyId: { + type: 'string' }, - "name": { - "type": "string" + name: { + type: 'string' }, - "icon": { - "type": "string" + icon: { + type: 'string' }, - "key": { - "type": "string" + key: { + type: 'string' }, - "exposable": { - "type": "boolean" + exposable: { + type: 'boolean' } }, - "required": [ - "keyId", - "name", - "icon", - "key", - "exposable" - ], - "additionalProperties": false + required: ['keyId', 'name', 'icon', 'key', 'exposable'], + additionalProperties: false } }, - "output": { - "CREATED": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "keyId": { - "type": "string" + output: { + CREATED: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + keyId: { + type: 'string' }, - "name": { - "type": "string" + name: { + type: 'string' }, - "icon": { - "type": "string" + icon: { + type: 'string' }, - "key": { - "type": "string" + key: { + type: 'string' }, - "exposable": { - "type": "boolean" + exposable: { + type: 'boolean' }, - "created": { - "type": "string" + created: { + type: 'string' }, - "updated": { - "type": "string" + updated: { + type: 'string' }, - "id": { - "type": "string" + id: { + type: 'string' }, - "collectionId": { - "type": "string" + collectionId: { + type: 'string' }, - "collectionName": { - "type": "string" + collectionName: { + type: 'string' } }, - "required": [ - "keyId", - "name", - "icon", - "key", - "exposable", - "created", - "updated", - "id", - "collectionId", - "collectionName" + required: [ + 'keyId', + 'name', + 'icon', + 'key', + 'exposable', + 'created', + 'updated', + 'id', + 'collectionId', + 'collectionName' ], - "additionalProperties": false + additionalProperties: false } } }, - "update": { - "method": "post", - "description": "Update an existing API key entry", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "id": { - "type": "string" + update: { + method: 'post', + description: 'Update an existing API key entry', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + id: { + type: 'string' } }, - "required": [ - "id" - ], - "additionalProperties": false + required: ['id'], + additionalProperties: false }, - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "keyId": { - "type": "string" + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + keyId: { + type: 'string' }, - "name": { - "type": "string" + name: { + type: 'string' }, - "icon": { - "type": "string" + icon: { + type: 'string' }, - "key": { - "type": "string" + key: { + type: 'string' }, - "exposable": { - "type": "boolean" + exposable: { + type: 'boolean' }, - "overrideKey": { - "type": "boolean" + overrideKey: { + type: 'boolean' } }, - "required": [ - "keyId", - "name", - "icon", - "key", - "exposable", - "overrideKey" + required: [ + 'keyId', + 'name', + 'icon', + 'key', + 'exposable', + 'overrideKey' ], - "additionalProperties": false + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "keyId": { - "type": "string" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + keyId: { + type: 'string' }, - "name": { - "type": "string" + name: { + type: 'string' }, - "icon": { - "type": "string" + icon: { + type: 'string' }, - "key": { - "type": "string" + key: { + type: 'string' }, - "exposable": { - "type": "boolean" + exposable: { + type: 'boolean' }, - "created": { - "type": "string" + created: { + type: 'string' }, - "updated": { - "type": "string" + updated: { + type: 'string' }, - "id": { - "type": "string" + id: { + type: 'string' }, - "collectionId": { - "type": "string" + collectionId: { + type: 'string' }, - "collectionName": { - "type": "string" + collectionName: { + type: 'string' } }, - "required": [ - "keyId", - "name", - "icon", - "key", - "exposable", - "created", - "updated", - "id", - "collectionId", - "collectionName" + required: [ + 'keyId', + 'name', + 'icon', + 'key', + 'exposable', + 'created', + 'updated', + 'id', + 'collectionId', + 'collectionName' ], - "additionalProperties": false + additionalProperties: false }, - "NOT_FOUND": true + NOT_FOUND: true } }, - "remove": { - "method": "post", - "description": "Delete an API key entry", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "id": { - "type": "string" + remove: { + method: 'post', + description: 'Delete an API key entry', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + id: { + type: 'string' } }, - "required": [ - "id" - ], - "additionalProperties": false + required: ['id'], + additionalProperties: false } }, - "output": { - "NO_CONTENT": true, - "NOT_FOUND": true + output: { + NO_CONTENT: true, + NOT_FOUND: true } } } }, - "pixabay": { - "searchImages": { - "method": "get", - "description": "Search for images on Pixabay", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "q": { - "type": "string", - "minLength": 1 + pixabay: { + searchImages: { + method: 'get', + description: 'Search for images on Pixabay', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + q: { + type: 'string', + minLength: 1 }, - "page": { - "default": "1", - "type": "string" + page: { + default: '1', + type: 'string' }, - "type": { - "default": "all", - "type": "string", - "enum": [ - "all", - "photo", - "illustration", - "vector" + type: { + default: 'all', + type: 'string', + enum: ['all', 'photo', 'illustration', 'vector'] + }, + category: { + type: 'string', + enum: [ + 'backgrounds', + 'fashion', + 'nature', + 'science', + 'education', + 'feelings', + 'health', + 'people', + 'religion', + 'places', + 'animals', + 'industry', + 'computer', + 'food', + 'sports', + 'transportation', + 'travel', + 'buildings', + 'business', + 'music' ] }, - "category": { - "type": "string", - "enum": [ - "backgrounds", - "fashion", - "nature", - "science", - "education", - "feelings", - "health", - "people", - "religion", - "places", - "animals", - "industry", - "computer", - "food", - "sports", - "transportation", - "travel", - "buildings", - "business", - "music" - ] - }, - "colors": { - "anyOf": [ + colors: { + anyOf: [ { - "type": "string", - "enum": [ - "grayscale", - "transparent", - "red", - "orange", - "yellow", - "green", - "turquoise", - "blue", - "lilac", - "pink", - "white", - "gray", - "black", - "brown" + type: 'string', + enum: [ + 'grayscale', + 'transparent', + 'red', + 'orange', + 'yellow', + 'green', + 'turquoise', + 'blue', + 'lilac', + 'pink', + 'white', + 'gray', + 'black', + 'brown' ] }, { - "type": "null" + type: 'null' } ] }, - "editors_choice": { - "default": "false", - "type": "string", - "enum": [ - "true", - "false" - ] + editors_choice: { + default: 'false', + type: 'string', + enum: ['true', 'false'] } }, - "required": [ - "q", - "page", - "type", - "editors_choice" - ], - "additionalProperties": false + required: ['q', 'page', 'type', 'editors_choice'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "total": { - "type": "number" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + total: { + type: 'number' }, - "hits": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" + hits: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string' }, - "thumbnail": { - "type": "object", - "properties": { - "url": { - "type": "string" + thumbnail: { + type: 'object', + properties: { + url: { + type: 'string' }, - "width": { - "type": "number" + width: { + type: 'number' }, - "height": { - "type": "number" + height: { + type: 'number' } }, - "required": [ - "url", - "width", - "height" - ], - "additionalProperties": false + required: ['url', 'width', 'height'], + additionalProperties: false }, - "imageURL": { - "type": "string" + imageURL: { + type: 'string' } }, - "required": [ - "id", - "thumbnail", - "imageURL" - ], - "additionalProperties": false + required: ['id', 'thumbnail', 'imageURL'], + additionalProperties: false } } }, - "required": [ - "total", - "hits" - ], - "additionalProperties": false + required: ['total', 'hits'], + additionalProperties: false }, - "BAD_REQUEST": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + BAD_REQUEST: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' } } } }, - "locations": { - "search": { - "method": "get", - "description": "Search for locations using Google Places API", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "q": { - "type": "string" + locations: { + search: { + method: 'get', + description: 'Search for locations using Google Places API', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + q: { + type: 'string' } }, - "required": [ - "q" - ], - "additionalProperties": false + required: ['q'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string' }, - "formattedAddress": { - "type": "string" + formattedAddress: { + type: 'string' }, - "location": { - "type": "object", - "properties": { - "latitude": { - "type": "number" + location: { + type: 'object', + properties: { + latitude: { + type: 'number' }, - "longitude": { - "type": "number" + longitude: { + type: 'number' } }, - "required": [ - "latitude", - "longitude" - ], - "additionalProperties": false + required: ['latitude', 'longitude'], + additionalProperties: false } }, - "required": [ - "name", - "formattedAddress", - "location" - ], - "additionalProperties": false + required: ['name', 'formattedAddress', 'location'], + additionalProperties: false } }, - "BAD_REQUEST": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + BAD_REQUEST: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' } } } }, - "backups": { - "list": { - "method": "get", - "description": "Retrieve all database backups", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "array", - "items": { - "type": "object", - "properties": { - "key": { - "type": "string" + backups: { + list: { + method: 'get', + description: 'Retrieve all database backups', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'array', + items: { + type: 'object', + properties: { + key: { + type: 'string' }, - "size": { - "type": "number" + size: { + type: 'number' }, - "modified": { - "type": "string" + modified: { + type: 'string' } }, - "required": [ - "key", - "size", - "modified" - ], - "additionalProperties": false + required: ['key', 'size', 'modified'], + additionalProperties: false } } } }, - "download": { - "method": "get", - "description": "Download a database backup file", - "noAuth": false, - "encrypted": true, - "isDownloadable": true, - "media": null, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "key": { - "type": "string" + download: { + method: 'get', + description: 'Download a database backup file', + noAuth: false, + encrypted: true, + isDownloadable: true, + media: null, + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + key: { + type: 'string' } }, - "required": [ - "key" - ], - "additionalProperties": false + required: ['key'], + additionalProperties: false } }, - "output": { - "NO_CONTENT": true, - "BAD_REQUEST": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + output: { + NO_CONTENT: true, + BAD_REQUEST: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' } } }, - "create": { - "method": "post", - "description": "Create a new database backup", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "backupName": { - "type": "string" + create: { + method: 'post', + description: 'Create a new database backup', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + backupName: { + type: 'string' } }, - "additionalProperties": false + additionalProperties: false } }, - "output": { - "CREATED": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "null" + output: { + CREATED: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'null' } } }, - "remove": { - "method": "post", - "description": "Delete a database backup", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "key": { - "type": "string" + remove: { + method: 'post', + description: 'Delete a database backup', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + key: { + type: 'string' } }, - "required": [ - "key" - ], - "additionalProperties": false + required: ['key'], + additionalProperties: false } }, - "output": { - "NO_CONTENT": true + output: { + NO_CONTENT: true } } }, - "database": { - "collections": { - "list": { - "method": "get", - "description": "Retrieve all database collections", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" + database: { + collections: { + list: { + method: 'get', + description: 'Retrieve all database collections', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string' }, - "type": { - "type": "string", - "enum": [ - "base", - "view" - ] + type: { + type: 'string', + enum: ['base', 'view'] }, - "fields": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" + fields: { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string' }, - "type": { - "type": "string" + type: { + type: 'string' }, - "optional": { - "type": "boolean" + optional: { + type: 'boolean' }, - "options": { - "type": "array", - "items": { - "type": "string" + options: { + type: 'array', + items: { + type: 'string' } } }, - "required": [ - "name", - "type", - "optional" - ], - "additionalProperties": false + required: ['name', 'type', 'optional'], + additionalProperties: false } } }, - "required": [ - "name", - "type", - "fields" - ], - "additionalProperties": false + required: ['name', 'type', 'fields'], + additionalProperties: false } } } } } }, - "modules": { - "checkModuleAvailability": { - "method": "get", - "description": "Check if a module is available (installed)", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "moduleId": { - "type": "string", - "minLength": 1 + modules: { + checkModuleAvailability: { + method: 'get', + description: 'Check if a module is available (installed)', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + moduleId: { + type: 'string', + minLength: 1 } }, - "required": [ - "moduleId" - ], - "additionalProperties": false + required: ['moduleId'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "boolean" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'boolean' } } }, - "list": { - "method": "get", - "description": "List installed modules with metadata", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" + list: { + method: 'get', + description: 'List installed modules with metadata', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string' }, - "moduleId": { - "type": "string" + moduleId: { + type: 'string' }, - "displayName": { - "type": "string" + displayName: { + type: 'string' }, - "version": { - "type": "string" + version: { + type: 'string' }, - "description": { - "type": "string" + description: { + type: 'string' }, - "author": { - "type": "string" + author: { + type: 'string' }, - "icon": { - "type": "string" + icon: { + type: 'string' }, - "category": { - "type": "string" + category: { + type: 'string' }, - "isInternal": { - "type": "boolean" + isInternal: { + type: 'boolean' }, - "isDevMode": { - "type": "boolean" + isDevMode: { + type: 'boolean' }, - "hasDist": { - "type": "boolean" + hasDist: { + type: 'boolean' }, - "hasSource": { - "type": "boolean" + hasSource: { + type: 'boolean' } }, - "required": [ - "name", - "moduleId", - "displayName", - "version", - "description", - "author", - "icon", - "category", - "isInternal", - "isDevMode", - "hasDist", - "hasSource" + required: [ + 'name', + 'moduleId', + 'displayName', + 'version', + 'description', + 'author', + 'icon', + 'category', + 'isInternal', + 'isDevMode', + 'hasDist', + 'hasSource' ], - "additionalProperties": false + additionalProperties: false } } } }, - "manifest": { - "method": "get", - "description": "Get installed modules manifest for runtime loading", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "modules": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" + manifest: { + method: 'get', + description: 'Get installed modules manifest for runtime loading', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + modules: { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string' }, - "moduleId": { - "type": "string" + moduleId: { + type: 'string' }, - "displayName": { - "type": "string" + displayName: { + type: 'string' }, - "version": { - "type": "string" + version: { + type: 'string' }, - "description": { - "type": "string" + description: { + type: 'string' }, - "author": { - "type": "string" + author: { + type: 'string' }, - "icon": { - "type": "string" + icon: { + type: 'string' }, - "category": { - "type": "string" + category: { + type: 'string' }, - "remoteEntryUrl": { - "type": "string" + remoteEntryUrl: { + type: 'string' }, - "isInternal": { - "type": "boolean" + isInternal: { + type: 'boolean' }, - "isDevMode": { - "type": "boolean" + isDevMode: { + type: 'boolean' }, - "APIKeyAccess": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "usage": { - "type": "string" + APIKeyAccess: { + type: 'object', + additionalProperties: { + type: 'object', + properties: { + usage: { + type: 'string' }, - "required": { - "type": "boolean" + required: { + type: 'boolean' } }, - "required": [ - "usage", - "required" - ], - "additionalProperties": false + required: ['usage', 'required'], + additionalProperties: false } } }, - "required": [ - "name", - "moduleId", - "displayName", - "version", - "description", - "author", - "icon", - "category", - "remoteEntryUrl", - "isInternal" + required: [ + 'name', + 'moduleId', + 'displayName', + 'version', + 'description', + 'author', + 'icon', + 'category', + 'remoteEntryUrl', + 'isInternal' ], - "additionalProperties": false + additionalProperties: false } } }, - "required": [ - "modules" - ], - "additionalProperties": false + required: ['modules'], + additionalProperties: false } } }, - "uninstall": { - "method": "post", - "description": "Uninstall a module", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "moduleName": { - "type": "string", - "minLength": 1 + uninstall: { + method: 'post', + description: 'Uninstall a module', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + moduleName: { + type: 'string', + minLength: 1 } }, - "required": [ - "moduleName" - ], - "additionalProperties": false + required: ['moduleName'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "success": { - "type": "boolean" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + success: { + type: 'boolean' }, - "error": { - "type": "string" + error: { + type: 'string' } }, - "required": [ - "success" - ], - "additionalProperties": false + required: ['success'], + additionalProperties: false } } }, - "categories": { - "aiTranslate": { - "method": "post", - "description": "Translate a specific category into desired languages", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "key": { - "type": "string" + categories: { + aiTranslate: { + method: 'post', + description: 'Translate a specific category into desired languages', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + key: { + type: 'string' }, - "languages": { - "type": "array", - "items": { - "type": "string" + languages: { + type: 'array', + items: { + type: 'string' } } }, - "required": [ - "key", - "languages" - ], - "additionalProperties": false + required: ['key', 'languages'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "anyOf": [ + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + anyOf: [ { - "type": "object", - "additionalProperties": { - "type": "string" + type: 'object', + additionalProperties: { + type: 'string' } }, { - "type": "null" + type: 'null' } ] } } }, - "list": { - "method": "get", - "description": "Get the category display order", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "additionalProperties": { - "type": "object", - "additionalProperties": { - "type": "string" + list: { + method: 'get', + description: 'Get the category display order', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + additionalProperties: { + type: 'object', + additionalProperties: { + type: 'string' } } } } }, - "update": { - "method": "post", - "description": "Update the category display order", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "data": { - "type": "object", - "additionalProperties": { - "type": "object", - "additionalProperties": { - "type": "string" + update: { + method: 'post', + description: 'Update the category display order', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + data: { + type: 'object', + additionalProperties: { + type: 'object', + additionalProperties: { + type: 'string' } } } }, - "required": [ - "data" - ], - "additionalProperties": false + required: ['data'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "success": { - "type": "boolean" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + success: { + type: 'boolean' } }, - "required": [ - "success" - ], - "additionalProperties": false + required: ['success'], + additionalProperties: false } } } }, - "devMode": { - "toggle": { - "method": "post", - "description": "Toggle dev mode for a module", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "moduleName": { - "type": "string", - "minLength": 1 + devMode: { + toggle: { + method: 'post', + description: 'Toggle dev mode for a module', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + moduleName: { + type: 'string', + minLength: 1 } }, - "required": [ - "moduleName" - ], - "additionalProperties": false + required: ['moduleName'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "boolean" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'boolean' } } } } }, - "ai": { - "imageGeneration": { - "generateImage": { - "method": "post", - "description": "Generate image from text prompt using AI", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "prompt": { - "type": "string", - "minLength": 1 + ai: { + imageGeneration: { + generateImage: { + method: 'post', + description: 'Generate image from text prompt using AI', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + prompt: { + type: 'string', + minLength: 1 } }, - "required": [ - "prompt" - ], - "additionalProperties": false + required: ['prompt'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' }, - "BAD_REQUEST": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + BAD_REQUEST: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' } } } } }, - "ping": { - "method": "post", - "description": "Ping the server", - "noAuth": true, - "encrypted": false, - "isDownloadable": false, - "media": null, - "input": { - "body": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "timestamp": { - "type": "number", - "minimum": 0 + ping: { + method: 'post', + description: 'Ping the server', + noAuth: true, + encrypted: false, + isDownloadable: false, + media: null, + input: { + body: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + timestamp: { + type: 'number', + minimum: 0 } }, - "required": [ - "timestamp" - ], - "additionalProperties": false + required: ['timestamp'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' } } }, - "status": { - "method": "get", - "description": "Get server status", - "noAuth": true, - "encrypted": false, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "environment": { - "type": "string" + status: { + method: 'get', + description: 'Get server status', + noAuth: true, + encrypted: false, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + environment: { + type: 'string' } }, - "required": [ - "environment" - ], - "additionalProperties": false + required: ['environment'], + additionalProperties: false } } }, - "media": { - "method": "get", - "description": "Retrieve media file from PocketBase", - "noAuth": true, - "encrypted": false, - "isDownloadable": false, - "media": null, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "collectionId": { - "type": "string" + media: { + method: 'get', + description: 'Retrieve media file from PocketBase', + noAuth: true, + encrypted: false, + isDownloadable: false, + media: null, + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + collectionId: { + type: 'string' }, - "recordId": { - "type": "string" + recordId: { + type: 'string' }, - "fieldId": { - "type": "string" + fieldId: { + type: 'string' }, - "thumb": { - "type": "string" + thumb: { + type: 'string' }, - "token": { - "type": "string" + token: { + type: 'string' } }, - "required": [ - "collectionId", - "recordId", - "fieldId" - ], - "additionalProperties": false + required: ['collectionId', 'recordId', 'fieldId'], + additionalProperties: false } }, - "output": "custom" + output: 'custom' }, - "corsAnywhere": { - "method": "get", - "description": "CORS Anywhere - Fetch external URL content", - "noAuth": false, - "encrypted": true, - "isDownloadable": false, - "media": null, - "input": { - "query": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "properties": { - "url": { - "type": "string", - "format": "uri" + corsAnywhere: { + method: 'get', + description: 'CORS Anywhere - Fetch external URL content', + noAuth: false, + encrypted: true, + isDownloadable: false, + media: null, + input: { + query: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'object', + properties: { + url: { + type: 'string', + format: 'uri' } }, - "required": [ - "url" - ], - "additionalProperties": false + required: ['url'], + additionalProperties: false } }, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema" + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema' }, - "BAD_REQUEST": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + BAD_REQUEST: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' } } }, - "encryptionPublicKey": { - "method": "get", - "description": "Get server public key for end-to-end encryption", - "noAuth": true, - "encrypted": false, - "isDownloadable": false, - "media": null, - "input": {}, - "output": { - "OK": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" + encryptionPublicKey: { + method: 'get', + description: 'Get server public key for end-to-end encryption', + noAuth: true, + encrypted: false, + isDownloadable: false, + media: null, + input: {}, + output: { + OK: { + $schema: 'https://json-schema.org/draft/2020-12/schema', + type: 'string' } } } diff --git a/packages/ui/src/providers/BackgroundProvider.tsx b/packages/ui/src/providers/BackgroundProvider.tsx index 858cc5be6..01eb5565f 100644 --- a/packages/ui/src/providers/BackgroundProvider.tsx +++ b/packages/ui/src/providers/BackgroundProvider.tsx @@ -1,8 +1,8 @@ -import { BG_BLURS } from './PersonalizationProvider/constants/bg_blurs' -import { usePersonalization } from './PersonalizationProvider' - import { Box, Flex } from '@/components/primitives' +import { usePersonalization } from './PersonalizationProvider' +import { BG_BLURS } from './PersonalizationProvider/constants/bg_blurs' + export function BackgroundProvider({ children }: { diff --git a/packages/ui/src/providers/PersonalizationProvider/hooks/useLanguageEffect.tsx b/packages/ui/src/providers/PersonalizationProvider/hooks/useLanguageEffect.tsx index 436d291ce..d3d2fa71c 100644 --- a/packages/ui/src/providers/PersonalizationProvider/hooks/useLanguageEffect.tsx +++ b/packages/ui/src/providers/PersonalizationProvider/hooks/useLanguageEffect.tsx @@ -1,5 +1,6 @@ import i18n from 'i18next' import { useEffect } from 'react' + import { toast } from '@/providers' function useLanguageEffect(language: string) { diff --git a/packages/ui/src/storybook/PreviewWrapper.tsx b/packages/ui/src/storybook/PreviewWrapper.tsx index 173e209d7..501052ae2 100644 --- a/packages/ui/src/storybook/PreviewWrapper.tsx +++ b/packages/ui/src/storybook/PreviewWrapper.tsx @@ -1,13 +1,13 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { QueryClient, QueryClientProvider } from '@tanstack/react-query' -import { ToastProvider } from '../providers' import { APIEndpointProvider } from '@lifeforge/api' import { ModalManager } from '@/components/overlays' import { Flex, Transition } from '@/components/primitives' import { ModalProvider } from '@/providers' +import { ToastProvider } from '../providers' import { SBThemeProvider } from './SBThemeProvider' export const queryClient = new QueryClient() diff --git a/packages/ui/src/storybook/SBThemeProvider.tsx b/packages/ui/src/storybook/SBThemeProvider.tsx index 577a04f08..8f3e27a2d 100644 --- a/packages/ui/src/storybook/SBThemeProvider.tsx +++ b/packages/ui/src/storybook/SBThemeProvider.tsx @@ -1,10 +1,9 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { type ReactNode, useMemo } from 'react' -import { PersonalizationProvider } from '../providers' - import { forgeAPI } from '@/utils/forgeAPI' +import { PersonalizationProvider } from '../providers' import { useSBTheme } from './useSBTheme' function deriveFinalValue(value: any, fallback: any) { diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json index 6bd503714..60513f54b 100644 --- a/packages/ui/tsconfig.json +++ b/packages/ui/tsconfig.json @@ -4,15 +4,9 @@ "jsx": "react-jsx", "module": "esnext", "moduleResolution": "bundler", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], + "lib": ["dom", "dom.iterable", "esnext"], "paths": { - "@/*": [ - "./src/*" - ] + "@/*": ["./src/*"] }, "declaration": true, "declarationMap": true, @@ -25,8 +19,5 @@ "skipLibCheck": true, "verbatimModuleSyntax": true }, - "include": [ - "./src/**/*", - "./.storybook/*" - ] -} \ No newline at end of file + "include": ["./src/**/*", "./.storybook/*"] +} diff --git a/server/src/core/functions/external/ai/index.ts b/server/src/core/functions/external/ai/index.ts index 920a0b81b..c064cd0b0 100644 --- a/server/src/core/functions/external/ai/index.ts +++ b/server/src/core/functions/external/ai/index.ts @@ -6,7 +6,6 @@ import OpenAI from 'openai' import z from 'zod' import { - CleanedSchemas, ClientError, FetchAIFunc, IPBService, @@ -33,7 +32,7 @@ async function fetchAI({ messages, structure }: { - pb: IPBService + pb: IPBService provider: 'groq' | 'openai' | 'ollama' | 'deepseek' model: string messages: OpenAI.ChatCompletionMessageParam[] diff --git a/server/src/core/functions/modules/loadModuleRoutes.ts b/server/src/core/functions/modules/loadModuleRoutes.ts index ea8548db0..8cee7a2c9 100644 --- a/server/src/core/functions/modules/loadModuleRoutes.ts +++ b/server/src/core/functions/modules/loadModuleRoutes.ts @@ -3,7 +3,6 @@ import { createServiceLogger } from '@functions/logging' import chalk from 'chalk' import crypto from 'crypto' import fs from 'fs' -import _ from 'lodash' import path from 'path' const IS_PRODUCTION = process.env.NODE_ENV === 'production' @@ -54,10 +53,13 @@ export async function loadModuleRoutes(): Promise> { const mod = await import(modulePath) const pkgPath = path.join(appsDir, modDir, 'package.json') + if (!fs.existsSync(pkgPath)) { continue } + const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) + const key = generateModuleId(pkg.name) if (!mod.default) { diff --git a/server/src/index.ts b/server/src/index.ts index b07a15db1..c619a5c00 100755 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -3,13 +3,14 @@ import checkDB from '@functions/database/dbUtils' import ensureCredentials from '@functions/initialization/ensureCredentials' import { LocaleService } from '@functions/initialization/localeService' import { LOG_LEVELS, type LogLevel, coreLogger } from '@functions/logging' -import { traceRouteStack } from '@lifeforge/server-utils' import createSocketServer from '@functions/socketio/createSocketServer' import chalk from 'chalk' import { program } from 'commander' import fs from 'fs' import { createServer } from 'node:http' +import { traceRouteStack } from '@lifeforge/server-utils' + import app from './core/app' // Parse CLI arguments diff --git a/tools/package.json b/tools/package.json index 7c6567ef0..d8f2bad25 100644 --- a/tools/package.json +++ b/tools/package.json @@ -23,7 +23,8 @@ "prompts": "^2.4.2", "semver": "^7.7.3", "zod": "4.3.5", - "@lifeforge/log": "workspace:*" + "@lifeforge/log": "workspace:*", + "@lifeforge/server-utils": "workspace:*" }, "devDependencies": { "@types/crypto-js": "^4.2.2", diff --git a/tools/src/commands/dev/functions/startServices.ts b/tools/src/commands/dev/functions/startServices.ts index 2bac28a30..95d8e7678 100644 --- a/tools/src/commands/dev/functions/startServices.ts +++ b/tools/src/commands/dev/functions/startServices.ts @@ -37,10 +37,12 @@ export async function startSingleService( // Add --host and --port flags for client service if provided const finalExtraArgs = [...extraArgs] + if (service === 'client') { if (host) { finalExtraArgs.push('--host') } + if (port) { finalExtraArgs.push('--port', port) } diff --git a/tools/src/commands/locales/constants/index.ts b/tools/src/commands/locales/constants/index.ts index e9449e6d9..e69de29bb 100644 --- a/tools/src/commands/locales/constants/index.ts +++ b/tools/src/commands/locales/constants/index.ts @@ -1,4 +0,0 @@ -import fs from 'fs' -import path from 'path' - -import logger from '@/utils/logger' diff --git a/tools/src/commands/locales/functions/listLocales.ts b/tools/src/commands/locales/functions/listLocales.ts index 09996cf8d..33f8e56df 100644 --- a/tools/src/commands/locales/functions/listLocales.ts +++ b/tools/src/commands/locales/functions/listLocales.ts @@ -2,7 +2,6 @@ import fs from 'fs' import path from 'path' import { LOCALES_DIR } from '@/constants/constants' -import logger from '@/utils/logger' export function listLocales(): string[] { return fs.readdirSync(LOCALES_DIR).filter(dir => { diff --git a/tools/src/commands/modules/functions/templates/copy-template.ts b/tools/src/commands/modules/functions/templates/copy-template.ts index 3bd9d8cc6..ce3032b47 100644 --- a/tools/src/commands/modules/functions/templates/copy-template.ts +++ b/tools/src/commands/modules/functions/templates/copy-template.ts @@ -3,7 +3,6 @@ import Handlebars from 'handlebars' import _ from 'lodash' import { ROOT_DIR } from '@/constants/constants' -import logger from '@/utils/logger' import type { AVAILABLE_TEMPLATE_MODULE_TYPES } from '../../handlers/createModuleHandler' diff --git a/tools/src/utils/bumpPackageVersion.ts b/tools/src/utils/bumpPackageVersion.ts index cf0b3cdd3..a15248f12 100644 --- a/tools/src/utils/bumpPackageVersion.ts +++ b/tools/src/utils/bumpPackageVersion.ts @@ -1,8 +1,6 @@ import fs from 'fs' import semver from 'semver' -import logger from '@/utils/logger' - /** * Bumps the patch version in a module's package.json file. * diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json index 2317088bd..645012a37 100644 --- a/tsconfig.eslint.json +++ b/tsconfig.eslint.json @@ -9,9 +9,5 @@ "scripts/**/*", "tools/**/*" ], - "exclude": [ - "**/node_modules", - "**/dist", - "**/dist-docker" - ] -} \ No newline at end of file + "exclude": ["**/node_modules", "**/dist", "**/dist-docker"] +} diff --git a/turbo.json b/turbo.json new file mode 100644 index 000000000..1a7c990a0 --- /dev/null +++ b/turbo.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://turbo.build/schema.json", + "tasks": { + "build": { + "dependsOn": ["^build"], + "outputs": ["dist/**", "client/dist/**", "server/dist/**"] + }, + "dev": { + "cache": false, + "persistent": true + }, + "types": { + "dependsOn": ["^types"] + }, + "lint": {}, + "test": { + "dependsOn": ["build"] + } + } +}