diff --git a/apps/backend/.gitignore b/apps/backend/.gitignore index 1fc874242..929ee98fc 100644 --- a/apps/backend/.gitignore +++ b/apps/backend/.gitignore @@ -46,6 +46,7 @@ lerna-debug.log* !/uploads/private/index.html !/uploads/temp/index.html -# Migrations +# Configuration /src/plugins/*/admin/database/migrations -/src/plugins/core/email.config.json \ No newline at end of file +/src/plugins/core/utils/config.json +/src/plugins/core/utils/email.config.json \ No newline at end of file diff --git a/apps/backend/schema.gql b/apps/backend/schema.gql index 1449a58c9..e0ce76d6b 100644 --- a/apps/backend/schema.gql +++ b/apps/backend/schema.gql @@ -2,6 +2,13 @@ # THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY) # ------------------------------------------------------ +enum AllowTypeFilesEnum { + all + images + images_videos + none +} + type AuthorizationAdminSessionsObj { nav: [NavAdminPluginsAuthorization!]! user: AuthorizationCurrentUserObj @@ -103,6 +110,11 @@ type EditAdminSettingsObj { site_name: String! } +type EditorShowCoreMiddleware { + files: FilesEditorShowCoreMiddleware! + sticky: Boolean! +} + type FilesAdminPluginsObj { admin_pages: Int! admin_templates: Int! @@ -120,6 +132,14 @@ type FilesAuthorizationCoreSessions { total_max_storage: Int! } +input FilesEditAdminEditorStyles { + allow_type: AllowTypeFilesEnum! +} + +type FilesEditorShowCoreMiddleware { + allow_type: AllowTypeFilesEnum! +} + type GroupUser { id: Int! name: [TextLanguage!]! @@ -176,10 +196,7 @@ type Mutation { admin__core_main_settings__edit(site_copyright: [TextLanguageInput!]!, site_description: [TextLanguageInput!]!, site_name: String!, site_short_name: String!): EditAdminSettingsObj! admin__core_manifest_metadata__edit(background_color: String!, display: String!, start_url: String!, theme_color: String!): ShowAdminManifestMetadataObj! admin__core_members__edit(birthday: DateTime!, email: String!, first_name: String!, id: Int!, last_name: String!, name: String!, newsletter: Boolean!): EditAdminMembersObj! - admin__core_nav__change_position(id: Int!, index_to_move: Int!, parent_id: Int!): String! - admin__core_nav__create(description: [TextLanguageInput!]!, external: Boolean!, href: String!, icon: String, name: [TextLanguageInput!]!): ShowCoreNav! - admin__core_nav__delete(id: Int!): String! - admin__core_nav__edit(description: [TextLanguageInput!]!, external: Boolean!, href: String!, icon: String, id: Int!, name: [TextLanguageInput!]!): ShowCoreNav! + admin__core_nav_styles__change_position(id: Int!, index_to_move: Int!, parent_id: Int!): String! admin__core_plugins__create(author: String!, author_url: String, code: String!, description: String, name: String!, support_url: String!): ShowAdminPlugins! admin__core_plugins__delete(code: String!): String! admin__core_plugins__download(code: String!, version: String, version_code: Int): String! @@ -193,6 +210,10 @@ type Mutation { admin__core_staff_administrators__delete(id: Int!): String! admin__core_staff_moderators__create(group_id: Int, unrestricted: Boolean!, user_id: Int): ShowAdminStaffModerators! admin__core_staff_moderators__delete(id: Int!): String! + admin__core_styles__editor__edit(files: FilesEditAdminEditorStyles!, sticky: Boolean!): EditorShowCoreMiddleware! + admin__core_styles__nav__create(description: [TextLanguageInput!]!, external: Boolean!, href: String!, icon: String, name: [TextLanguageInput!]!): ShowCoreNav! + admin__core_styles__nav__delete(id: Int!): String! + admin__core_styles__nav__edit(description: [TextLanguageInput!]!, external: Boolean!, href: String!, icon: String, id: Int!, name: [TextLanguageInput!]!): ShowCoreNav! admin__core_theme_editor__edit(colors: ColorsEditAdminThemeEditor!): String! admin__install__create_database: String! admin_sessions__sign_out: String! @@ -257,6 +278,11 @@ type Query { core_theme_editor__show: ShowCoreThemeEditorObj! } +type RebuildRequiredEditorShowCoreMiddleware { + langs: Boolean! + plugins: Boolean! +} + type ShowAdminEmailSettingsServiceObj { color_primary: String! smtp_host: String! @@ -556,8 +582,10 @@ enum ShowCoreMembersSortingColumnEnum { } type ShowCoreMiddlewareObj { + editor: EditorShowCoreMiddleware! languages: [LanguagesCoreMiddleware!]! plugins: [String!]! + rebuild_required: RebuildRequiredEditorShowCoreMiddleware! } type ShowCoreNav { diff --git a/apps/docs/pages/docs/deployment/install.mdx b/apps/docs/pages/docs/deployment/install.mdx index d0b5a4157..88fc9715a 100644 --- a/apps/docs/pages/docs/deployment/install.mdx +++ b/apps/docs/pages/docs/deployment/install.mdx @@ -79,5 +79,4 @@ Now, let's move to the [security server](setup/secure) part. sudo docker rm -v -f $(docker ps -qa) sudo docker rmi $(docker images -a -q) sudo docker system prune -a -sudo rm -r /home/vitnode/docker && sudo rm /home/vitnode/frontend/utils/config.json ``` diff --git a/apps/frontend/.gitignore b/apps/frontend/.gitignore index 3b6e56d2c..53e355fd4 100644 --- a/apps/frontend/.gitignore +++ b/apps/frontend/.gitignore @@ -33,7 +33,6 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts -utils/config.json /public/assets /public/uploads \ No newline at end of file diff --git a/apps/frontend/Dockerfile b/apps/frontend/Dockerfile index df4c4f054..1758fab0d 100644 --- a/apps/frontend/Dockerfile +++ b/apps/frontend/Dockerfile @@ -38,8 +38,6 @@ ENV NEXT_TELEMETRY_DISABLED 1 RUN pnpm turbo build --filter=frontend... -# COPY frontend/utils/config.json ./frontend/utils/config.json - FROM base AS runner WORKDIR /app @@ -55,11 +53,9 @@ WORKDIR /app # # https://nextjs.org/docs/advanced-features/output-file-tracing # COPY --from=installer --chown=nextjs:nodejs /app/frontend/.next/standalone ./ # COPY --from=installer --chown=nextjs:nodejs /app/frontend/.next/static ./frontend/.next/static -# COPY --from=installer --chown=nextjs:nodejs /app/frontend/utils/config.json ./frontend/utils/config.json COPY --from=installer /app/frontend/.next/standalone ./ COPY --from=installer /app/frontend/.next/static ./frontend/.next/static -COPY --from=installer /app/frontend/utils/config.json ./frontend/config.json EXPOSE 3000 ENV PORT 3000 diff --git a/apps/frontend/app/[locale]/(admin)/admin/(auth)/blog/layout.tsx b/apps/frontend/app/[locale]/(admin)/admin/(auth)/blog/layout.tsx index 93405843b..d36cdff9a 100644 --- a/apps/frontend/app/[locale]/(admin)/admin/(auth)/blog/layout.tsx +++ b/apps/frontend/app/[locale]/(admin)/admin/(auth)/blog/layout.tsx @@ -1,20 +1,20 @@ import { Metadata } from 'next'; import { getTranslations } from 'next-intl/server'; import * as React from 'react'; -import { getConfigFile } from 'vitnode-frontend/helpers/config'; +import { getGlobalData } from 'vitnode-frontend/graphql/get-global-data'; interface Props { children: React.ReactNode; } export async function generateMetadata(): Promise { - const [config, t, tAdmin] = await Promise.all([ - getConfigFile(), + const [data, t, tAdmin] = await Promise.all([ + getGlobalData(), getTranslations('blog.admin.nav'), getTranslations('admin'), ]); - const defaultTitle = `${t('title')} - ${tAdmin('title_short')} - ${config.settings.general.site_name}`; + const defaultTitle = `${t('title')} - ${tAdmin('title_short')} - ${data.core_settings__show.site_name}`; return { title: { diff --git a/apps/frontend/app/[locale]/(admin)/admin/(auth)/core/settings/layout.tsx b/apps/frontend/app/[locale]/(admin)/admin/(auth)/core/settings/layout.tsx index 34c81815c..a98be9e2d 100644 --- a/apps/frontend/app/[locale]/(admin)/admin/(auth)/core/settings/layout.tsx +++ b/apps/frontend/app/[locale]/(admin)/admin/(auth)/core/settings/layout.tsx @@ -1,20 +1,20 @@ import { getTranslations } from 'next-intl/server'; import * as React from 'react'; import { Metadata } from 'next'; -import { getConfigFile } from 'vitnode-frontend/helpers/config'; +import { getGlobalData } from 'vitnode-frontend/graphql/get-global-data'; interface Props { children: React.ReactNode; } export async function generateMetadata(): Promise { - const [t, tCore, config] = await Promise.all([ + const [t, tCore, data] = await Promise.all([ getTranslations('admin'), getTranslations('core.admin'), - getConfigFile(), + getGlobalData(), ]); - const defaultTitle = `${tCore('nav.settings')} - ${t('title_short')} - ${config.settings.general.site_name}`; + const defaultTitle = `${tCore('nav.settings')} - ${t('title_short')} - ${data.core_settings__show.site_name}`; return { title: { diff --git a/apps/frontend/app/[locale]/(admin)/admin/(auth)/layout.tsx b/apps/frontend/app/[locale]/(admin)/admin/(auth)/layout.tsx index af7006bd5..ee46338db 100644 --- a/apps/frontend/app/[locale]/(admin)/admin/(auth)/layout.tsx +++ b/apps/frontend/app/[locale]/(admin)/admin/(auth)/layout.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { getTranslations } from 'next-intl/server'; import { Metadata } from 'next'; -import { getConfigFile } from 'vitnode-frontend/helpers/config'; +import { getGlobalData } from 'vitnode-frontend/graphql/get-global-data'; import { AdminLayout } from 'vitnode-frontend/views/admin/layout/admin-layout'; import { AuthAdminLayout } from 'vitnode-frontend/views/admin/layout/auth/auth-admin-layout'; @@ -10,12 +10,12 @@ interface Props { } export async function generateMetadata(): Promise { - const [config, t] = await Promise.all([ - getConfigFile(), + const [data, t] = await Promise.all([ + getGlobalData(), getTranslations('admin'), ]); - const defaultTitle = `${t('title_short')} - ${config.settings.general.site_name}`; + const defaultTitle = `${t('title_short')} - ${data.core_settings__show.site_name}`; return { title: { diff --git a/apps/frontend/app/[locale]/(main)/(container)/settings/layout.tsx b/apps/frontend/app/[locale]/(main)/(container)/settings/layout.tsx index 4c4ada222..8eace9fab 100644 --- a/apps/frontend/app/[locale]/(main)/(container)/settings/layout.tsx +++ b/apps/frontend/app/[locale]/(main)/(container)/settings/layout.tsx @@ -1,21 +1,23 @@ import * as React from 'react'; import { Metadata } from 'next'; import { getTranslations } from 'next-intl/server'; -import { getConfigFile } from 'vitnode-frontend/helpers/config'; import { LayoutSettingsView } from 'vitnode-frontend/theme-tsx/settings/layout-settings-view'; +import { getGlobalData } from 'vitnode-frontend/graphql/get-global-data'; interface Props { children: React.ReactNode; } export async function generateMetadata(): Promise { - const config = await getConfigFile(); - const t = await getTranslations('core.settings'); + const [data, t] = await Promise.all([ + getGlobalData(), + getTranslations('core.settings'), + ]); return { title: { default: t('title'), - template: `%s - ${t('title')} - ${config.settings.general.site_name}`, + template: `%s - ${t('title')} - ${data.core_settings__show.site_name}`, }, robots: 'noindex, nofollow', }; diff --git a/apps/frontend/app/[locale]/(main)/page.tsx b/apps/frontend/app/[locale]/(main)/page.tsx index cf1e005af..805cf9db0 100644 --- a/apps/frontend/app/[locale]/(main)/page.tsx +++ b/apps/frontend/app/[locale]/(main)/page.tsx @@ -14,9 +14,7 @@ const getDescription = async ({ locale: Props['params']['locale']; }): Promise => { const { - data: { - core_settings__show: { site_description }, - }, + core_settings__show: { site_description }, } = await getSessionData(); const textFromLang = site_description.find(t => t.language_code === locale); @@ -37,11 +35,13 @@ export async function generateMetadata({ } export default async function Page() { - const { default_plugin } = await getSessionData(); + const { + core_sessions__authorization: { plugin_default }, + } = await getSessionData(); const PageFromTheme: React.LazyExoticComponent<() => JSX.Element> = React.lazy( async () => - import(`../../../plugins/${default_plugin}/templates/default-page`), + import(`../../../plugins/${plugin_default}/templates/default-page`), ); return ; diff --git a/apps/frontend/app/sitemap.ts b/apps/frontend/app/sitemap.ts index 2f8133dd2..7168f7828 100644 --- a/apps/frontend/app/sitemap.ts +++ b/apps/frontend/app/sitemap.ts @@ -20,10 +20,8 @@ const generateAlternateLanguagesForSitemap = ({ export default async function sitemap(): Promise { const { - data: { - core_languages__show: { edges: languages }, - core_plugins__show, - }, + core_languages__show: { edges: languages }, + core_plugins__show, } = await getSessionData(); const plugins = core_plugins__show.filter(item => item.allow_default); diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 87d1ca54d..c82b872f4 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -4,8 +4,7 @@ "author": "Maciej Piotr (aXenDev) Balcerzak", "license": "GPL-3.0 license", "scripts": { - "config:init": "vitnode-frontend init", - "dev": "pnpm config:init && next dev --turbo", + "dev": "next dev --turbo", "dev:turbo": "next dev --turbo", "build": "next build", "analyze": "cross-env ANALYZE=true pnpm build", diff --git a/apps/frontend/utils/graphql.ts b/apps/frontend/utils/graphql.ts index 5836d2155..30c5ef3df 100644 --- a/apps/frontend/utils/graphql.ts +++ b/apps/frontend/utils/graphql.ts @@ -17,6 +17,14 @@ export type Scalars = { Upload: { input: any; output: any; } }; +export const AllowTypeFilesEnum = { + all: 'all', + images: 'images', + images_videos: 'images_videos', + none: 'none' +} as const; + +export type AllowTypeFilesEnum = typeof AllowTypeFilesEnum[keyof typeof AllowTypeFilesEnum]; export type AuthorizationAdminSessionsObj = { __typename?: 'AuthorizationAdminSessionsObj'; nav: Array; @@ -40,6 +48,7 @@ export type AuthorizationCurrentUserObj = { id: Scalars['Int']['output']; is_admin: Scalars['Boolean']['output']; is_mod: Scalars['Boolean']['output']; + language: Scalars['String']['output']; name: Scalars['String']['output']; name_seo: Scalars['String']['output']; newsletter: Scalars['Boolean']['output']; @@ -120,6 +129,12 @@ export type EditAdminSettingsObj = { site_name: Scalars['String']['output']; }; +export type EditorShowCoreMiddleware = { + __typename?: 'EditorShowCoreMiddleware'; + files: FilesEditorShowCoreMiddleware; + sticky: Scalars['Boolean']['output']; +}; + export type FilesAdminPluginsObj = { __typename?: 'FilesAdminPluginsObj'; admin_pages: Scalars['Int']['output']; @@ -139,6 +154,15 @@ export type FilesAuthorizationCoreSessions = { total_max_storage: Scalars['Int']['output']; }; +export type FilesEditAdminEditorStyles = { + allow_type: AllowTypeFilesEnum | `${AllowTypeFilesEnum}`; +}; + +export type FilesEditorShowCoreMiddleware = { + __typename?: 'FilesEditorShowCoreMiddleware'; + allow_type: AllowTypeFilesEnum | `${AllowTypeFilesEnum}`; +}; + export type GroupUser = { __typename?: 'GroupUser'; id: Scalars['Int']['output']; @@ -201,10 +225,7 @@ export type Mutation = { admin__core_main_settings__edit: EditAdminSettingsObj; admin__core_manifest_metadata__edit: ShowAdminManifestMetadataObj; admin__core_members__edit: EditAdminMembersObj; - admin__core_nav__change_position: Scalars['String']['output']; - admin__core_nav__create: ShowCoreNav; - admin__core_nav__delete: Scalars['String']['output']; - admin__core_nav__edit: ShowCoreNav; + admin__core_nav_styles__change_position: Scalars['String']['output']; admin__core_plugins__create: ShowAdminPlugins; admin__core_plugins__delete: Scalars['String']['output']; admin__core_plugins__download: Scalars['String']['output']; @@ -218,6 +239,10 @@ export type Mutation = { admin__core_staff_administrators__delete: Scalars['String']['output']; admin__core_staff_moderators__create: ShowAdminStaffModerators; admin__core_staff_moderators__delete: Scalars['String']['output']; + admin__core_styles__editor__edit: EditorShowCoreMiddleware; + admin__core_styles__nav__create: ShowCoreNav; + admin__core_styles__nav__delete: Scalars['String']['output']; + admin__core_styles__nav__edit: ShowCoreNav; admin__core_theme_editor__edit: Scalars['String']['output']; admin__install__create_database: Scalars['String']['output']; admin_sessions__sign_out: Scalars['String']['output']; @@ -227,9 +252,10 @@ export type Mutation = { core_members__avatar__delete: Scalars['String']['output']; core_members__avatar__upload: UploadAvatarCoreMembersObj; core_members__delete: Scalars['String']['output']; - core_members__sign_up: SignUpCoreMembersObj; + core_members__reset_password__create_key: Scalars['String']['output']; core_sessions__sign_in: Scalars['String']['output']; core_sessions__sign_out: Scalars['String']['output']; + core_sessions__sign_up: SignUpCoreSessionsObj; }; @@ -255,6 +281,7 @@ export type MutationAdmin__Core_Email_Settings__EditArgs = { export type MutationAdmin__Core_Email_Settings__TestArgs = { from: Scalars['String']['input']; message: Scalars['String']['input']; + preview_text?: InputMaybe; subject: Scalars['String']['input']; to: Scalars['String']['input']; }; @@ -343,37 +370,13 @@ export type MutationAdmin__Core_Members__EditArgs = { }; -export type MutationAdmin__Core_Nav__Change_PositionArgs = { +export type MutationAdmin__Core_Nav_Styles__Change_PositionArgs = { id: Scalars['Int']['input']; index_to_move: Scalars['Int']['input']; parent_id: Scalars['Int']['input']; }; -export type MutationAdmin__Core_Nav__CreateArgs = { - description: Array; - external: Scalars['Boolean']['input']; - href: Scalars['String']['input']; - icon?: InputMaybe; - name: Array; -}; - - -export type MutationAdmin__Core_Nav__DeleteArgs = { - id: Scalars['Int']['input']; -}; - - -export type MutationAdmin__Core_Nav__EditArgs = { - description: Array; - external: Scalars['Boolean']['input']; - href: Scalars['String']['input']; - icon?: InputMaybe; - id: Scalars['Int']['input']; - name: Array; -}; - - export type MutationAdmin__Core_Plugins__CreateArgs = { author: Scalars['String']['input']; author_url?: InputMaybe; @@ -472,6 +475,36 @@ export type MutationAdmin__Core_Staff_Moderators__DeleteArgs = { }; +export type MutationAdmin__Core_Styles__Editor__EditArgs = { + files: FilesEditAdminEditorStyles; + sticky: Scalars['Boolean']['input']; +}; + + +export type MutationAdmin__Core_Styles__Nav__CreateArgs = { + description: Array; + external: Scalars['Boolean']['input']; + href: Scalars['String']['input']; + icon?: InputMaybe; + name: Array; +}; + + +export type MutationAdmin__Core_Styles__Nav__DeleteArgs = { + id: Scalars['Int']['input']; +}; + + +export type MutationAdmin__Core_Styles__Nav__EditArgs = { + description: Array; + external: Scalars['Boolean']['input']; + href: Scalars['String']['input']; + icon?: InputMaybe; + id: Scalars['Int']['input']; + name: Array; +}; + + export type MutationAdmin__Core_Theme_Editor__EditArgs = { colors: ColorsEditAdminThemeEditor; }; @@ -506,11 +539,8 @@ export type MutationCore_Members__DeleteArgs = { }; -export type MutationCore_Members__Sign_UpArgs = { +export type MutationCore_Members__Reset_Password__Create_KeyArgs = { email: Scalars['String']['input']; - name: Scalars['String']['input']; - newsletter?: InputMaybe; - password: Scalars['String']['input']; }; @@ -521,6 +551,14 @@ export type MutationCore_Sessions__Sign_InArgs = { remember?: InputMaybe; }; + +export type MutationCore_Sessions__Sign_UpArgs = { + email: Scalars['String']['input']; + name: Scalars['String']['input']; + newsletter?: InputMaybe; + password: Scalars['String']['input']; +}; + export type NavAdminPluginsAuthorization = { __typename?: 'NavAdminPluginsAuthorization'; code: Scalars['String']['output']; @@ -679,6 +717,12 @@ export type QueryCore_Nav__ShowArgs = { last?: InputMaybe; }; +export type RebuildRequiredEditorShowCoreMiddleware = { + __typename?: 'RebuildRequiredEditorShowCoreMiddleware'; + langs: Scalars['Boolean']['output']; + plugins: Scalars['Boolean']['output']; +}; + export type ShowAdminEmailSettingsServiceObj = { __typename?: 'ShowAdminEmailSettingsServiceObj'; color_primary: Scalars['String']['output']; @@ -761,6 +805,7 @@ export type ShowAdminMembers = { group: GroupUser; id: Scalars['Int']['output']; joined: Scalars['DateTime']['output']; + language: Scalars['String']['output']; name: Scalars['String']['output']; name_seo: Scalars['String']['output']; newsletter: Scalars['Boolean']['output']; @@ -980,6 +1025,7 @@ export type ShowCoreMembers = { group: GroupUser; id: Scalars['Int']['output']; joined: Scalars['DateTime']['output']; + language: Scalars['String']['output']; name: Scalars['String']['output']; name_seo: Scalars['String']['output']; posts: Scalars['Int']['output']; @@ -1009,8 +1055,10 @@ export const ShowCoreMembersSortingColumnEnum = { export type ShowCoreMembersSortingColumnEnum = typeof ShowCoreMembersSortingColumnEnum[keyof typeof ShowCoreMembersSortingColumnEnum]; export type ShowCoreMiddlewareObj = { __typename?: 'ShowCoreMiddlewareObj'; + editor: EditorShowCoreMiddleware; languages: Array; plugins: Array; + rebuild_required: RebuildRequiredEditorShowCoreMiddleware; }; export type ShowCoreNav = { @@ -1074,8 +1122,8 @@ export type ShowSettingsObj = { site_short_name: Scalars['String']['output']; }; -export type SignUpCoreMembersObj = { - __typename?: 'SignUpCoreMembersObj'; +export type SignUpCoreSessionsObj = { + __typename?: 'SignUpCoreSessionsObj'; email: Scalars['String']['output']; group_id: Scalars['Int']['output']; name: Scalars['String']['output']; @@ -1141,6 +1189,7 @@ export type User = { avatar_color: Scalars['String']['output']; group: GroupUser; id: Scalars['Int']['output']; + language: Scalars['String']['output']; name: Scalars['String']['output']; name_seo: Scalars['String']['output']; }; diff --git a/docker-prod.sh b/docker-prod.sh index 638c34ff6..0ec73c57a 100644 --- a/docker-prod.sh +++ b/docker-prod.sh @@ -3,8 +3,5 @@ # Run docker-compose docker compose -f ./docker-compose.yml -p vitnode up -d --build -# Copy config.json from container to local -docker cp vitnode_frontend:/app/frontend/config.json ./frontend/utils/config.json - # Prune docker images docker image prune -a -f \ No newline at end of file diff --git a/packages/backend/scripts/generate-config.ts b/packages/backend/scripts/generate-config.ts new file mode 100644 index 000000000..a827ee5fb --- /dev/null +++ b/packages/backend/scripts/generate-config.ts @@ -0,0 +1,47 @@ +import * as fs from 'fs'; +import { join } from 'path'; + +import { DEFAULT_CONFIG_DATA, getConfigFile } from '../src/providers/config'; +import { updateObject } from './helpers/update-object'; + +export const generateConfig = ({ pluginsPath }: { pluginsPath: string }) => { + const folderPath = join(pluginsPath, 'core', 'utils'); + if (!fs.existsSync(folderPath)) { + fs.mkdirSync(folderPath, { recursive: true }); + } + + const configPath = join(folderPath, 'config.json'); + if (!fs.existsSync(configPath)) { + fs.writeFileSync( + configPath, + JSON.stringify( + { + ...DEFAULT_CONFIG_DATA, + lang: [ + { code: 'en', enabled: true }, + { code: 'pl', enabled: true }, + ], + }, + null, + 2, + ), + 'utf8', + ); + + return; + } + + const config = getConfigFile(); + const updatedConfig = updateObject( + { + ...config, + rebuild_required: { + langs: false, + plugins: false, + }, + }, + DEFAULT_CONFIG_DATA, + ); + + fs.writeFileSync(configPath, JSON.stringify(updatedConfig, null, 2), 'utf8'); +}; diff --git a/packages/backend/scripts/generate-manifest.ts b/packages/backend/scripts/generate-manifest.ts index 35ecc9203..66d980790 100644 --- a/packages/backend/scripts/generate-manifest.ts +++ b/packages/backend/scripts/generate-manifest.ts @@ -99,15 +99,16 @@ export const generateManifest = () => { const configPath = join( process.cwd(), - '..', - 'frontend', + 'src', + 'plugins', + 'core', 'utils', 'config.json', ); if (!fs.existsSync(configPath)) { console.log( - `⛔️ Config file not found in 'frontend/config' directory. "${configPath}"`, + `⛔️ Config file not found in 'backend/utils/config.json' directory. "${configPath}"`, ); process.exit(1); } diff --git a/packages/backend/scripts/setup.ts b/packages/backend/scripts/setup.ts index 07e04debf..bce14f50d 100755 --- a/packages/backend/scripts/setup.ts +++ b/packages/backend/scripts/setup.ts @@ -11,6 +11,7 @@ import { updatePlugins } from './update-plugins'; import { DATABASE_ENVS, createClientDatabase } from '../src/database/client'; import coreSchemaDatabase from '../src/templates/core/admin/database'; import { generateDatabaseMigrations } from './generate-database-migrations'; +import { generateConfig } from './generate-config'; const init = async () => { const pluginsPath = join(process.cwd(), 'src', 'plugins'); @@ -30,32 +31,39 @@ const init = async () => { console.log( '\x1b[34m%s\x1b[0m', '[VitNode]', - '[1/5] Setup the project. Copying the database core schema...', + '[1/6] Setup the project. Generating the config file...', + ); + generateConfig({ pluginsPath }); + + console.log( + '\x1b[34m%s\x1b[0m', + '[VitNode]', + '[2/6] Copying the database core schema...', ); copyDatabaseSchema({ corePluginPath }); console.log( '\x1b[34m%s\x1b[0m', '[VitNode]', - '[2/5] Generating database migrations...', + '[3/6] Generating database migrations...', ); await generateDatabaseMigrations({ pluginsPath }); console.log( '\x1b[34m%s\x1b[0m', '[VitNode]', - '[3/5] Generating the manifest files...', + '[4/6] Generating the manifest files...', ); generateManifest(); console.log( '\x1b[34m%s\x1b[0m', '[VitNode]', - '[4/5] Generating migrations...', + '[5/6] Generating migrations...', ); await generateMigrations({ pluginsPath, db: database.db }); - console.log('\x1b[34m%s\x1b[0m', '[VitNode]', '[5/5] Updating plugins...'); + console.log('\x1b[34m%s\x1b[0m', '[VitNode]', '[6/6] Updating plugins...'); await updatePlugins({ pluginsPath, db: database.db }); await database.poolDB.end(); diff --git a/packages/backend/scripts/update-plugins.ts b/packages/backend/scripts/update-plugins.ts index 3900c16ab..33608a5b5 100644 --- a/packages/backend/scripts/update-plugins.ts +++ b/packages/backend/scripts/update-plugins.ts @@ -5,7 +5,7 @@ import { join } from 'path'; import { NodePgDatabase } from 'drizzle-orm/node-postgres'; import { eq } from 'drizzle-orm'; -import { ConfigPlugin } from '../src'; +import { ConfigPlugin } from '../src/providers/plugins.type'; import coreSchemaDatabase from '../src/templates/core/admin/database'; import { core_plugins } from '../src/templates/core/admin/database/schema/plugins'; diff --git a/packages/backend/src/core/admin/admin.module.ts b/packages/backend/src/core/admin/admin.module.ts index d036f0ce8..68d3c1c06 100644 --- a/packages/backend/src/core/admin/admin.module.ts +++ b/packages/backend/src/core/admin/admin.module.ts @@ -5,7 +5,6 @@ import { GlobalAdminSessionsModule, } from './sessions/sessions.module'; import { AdminPluginsModule } from './plugins/plugins.module'; -import { AdminNavModule } from './nav/nav.module'; import { AdminStaffModule } from './staff/staff.module'; import { AdminLanguagesModule } from './languages/languages.module'; import { AdminFilesModule } from './files/files.module'; @@ -16,6 +15,7 @@ import { AdminSettingsModule } from './settings/settings.module'; import { AdminThemeEditorModule } from './theme_editor/theme_editor.module'; import { AdminInstallModule } from './install/install.module'; import { AdminEmailModule, GlobalAdminEmailModule } from './email/email.module'; +import { AdminStylesModule } from './styles/styles.module'; @Module({ imports: [ @@ -23,7 +23,7 @@ import { AdminEmailModule, GlobalAdminEmailModule } from './email/email.module'; GlobalAdminEmailModule, AdminSessionsModule, AdminPluginsModule, - AdminNavModule, + AdminStylesModule, AdminStaffModule, AdminLanguagesModule, AdminFilesModule, diff --git a/packages/backend/src/core/admin/email/helpers.service.ts b/packages/backend/src/core/admin/email/helpers.service.ts index b1670bbbd..f11eb530e 100644 --- a/packages/backend/src/core/admin/email/helpers.service.ts +++ b/packages/backend/src/core/admin/email/helpers.service.ts @@ -15,6 +15,7 @@ export interface ShowAdminEmailSettingsServiceObjWithPassword export class HelpersAdminEmailSettingsService { protected readonly path: string = join( ABSOLUTE_PATHS_BACKEND.plugin({ code: 'core' }).root, + 'utils', 'email.config.json', ); } diff --git a/packages/backend/src/core/admin/nav/change_position/change_position.resolver.ts b/packages/backend/src/core/admin/nav/change_position/change_position.resolver.ts deleted file mode 100644 index 86135d210..000000000 --- a/packages/backend/src/core/admin/nav/change_position/change_position.resolver.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Args, Mutation, Resolver } from '@nestjs/graphql'; -import { UseGuards } from '@nestjs/common'; - -import { ChangePositionAdminNavService } from './change_position.service'; -import { ChangePositionAdminNavArgs } from './dto/change_position.args'; - -import { AdminAuthGuards } from '../../../../utils'; - -@Resolver() -export class ChangePositionAdminNavResolver { - constructor(private readonly service: ChangePositionAdminNavService) {} - - @Mutation(() => String) - @UseGuards(AdminAuthGuards) - async admin__core_nav__change_position( - @Args() args: ChangePositionAdminNavArgs, - ): Promise { - return this.service.changePosition(args); - } -} diff --git a/packages/backend/src/core/admin/nav/create/create.resolver.ts b/packages/backend/src/core/admin/nav/create/create.resolver.ts deleted file mode 100644 index e0550fe58..000000000 --- a/packages/backend/src/core/admin/nav/create/create.resolver.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Args, Mutation, Resolver } from '@nestjs/graphql'; -import { UseGuards } from '@nestjs/common'; - -import { CreateAdminNavService } from './create.service'; -import { CreateAdminNavArgs } from './dto/create.args'; - -import { ShowCoreNav } from '../../../nav/show/dto/show.obj'; -import { AdminAuthGuards } from '../../../../utils'; - -@Resolver() -export class CreateAdminNavResolver { - constructor(private readonly service: CreateAdminNavService) {} - - @Mutation(() => ShowCoreNav) - @UseGuards(AdminAuthGuards) - async admin__core_nav__create( - @Args() args: CreateAdminNavArgs, - ): Promise { - return this.service.create(args); - } -} diff --git a/packages/backend/src/core/admin/nav/delete/delete.resolver.ts b/packages/backend/src/core/admin/nav/delete/delete.resolver.ts deleted file mode 100644 index 351bd7423..000000000 --- a/packages/backend/src/core/admin/nav/delete/delete.resolver.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Args, Mutation, Resolver } from '@nestjs/graphql'; -import { UseGuards } from '@nestjs/common'; - -import { DeleteAdminNavService } from './delete.service'; -import { DeleteAdminNavArgs } from './dto/delete.args'; - -import { AdminAuthGuards } from '../../../../utils'; - -@Resolver() -export class DeleteAdminNavResolver { - constructor(private readonly service: DeleteAdminNavService) {} - - @Mutation(() => String) - @UseGuards(AdminAuthGuards) - async admin__core_nav__delete( - @Args() args: DeleteAdminNavArgs, - ): Promise { - return this.service.delete(args); - } -} diff --git a/packages/backend/src/core/admin/nav/edit/dto/edit.args.ts b/packages/backend/src/core/admin/nav/edit/dto/edit.args.ts deleted file mode 100644 index b8185cbed..000000000 --- a/packages/backend/src/core/admin/nav/edit/dto/edit.args.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ArgsType, Field, Int } from '@nestjs/graphql'; - -import { CreateAdminNavArgs } from '../../create/dto/create.args'; - -@ArgsType() -export class EditAdminNavArgs extends CreateAdminNavArgs { - @Field(() => Int) - id: number; -} diff --git a/packages/backend/src/core/admin/nav/edit/edit.resolver.ts b/packages/backend/src/core/admin/nav/edit/edit.resolver.ts deleted file mode 100644 index a8de1f712..000000000 --- a/packages/backend/src/core/admin/nav/edit/edit.resolver.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Args, Mutation, Resolver } from '@nestjs/graphql'; -import { UseGuards } from '@nestjs/common'; - -import { EditAdminNavService } from './edit.service'; -import { EditAdminNavArgs } from './dto/edit.args'; - -import { ShowCoreNav } from '../../../nav/show/dto/show.obj'; -import { AdminAuthGuards } from '../../../../utils'; - -@Resolver() -export class EditAdminNavResolver { - constructor(private readonly service: EditAdminNavService) {} - - @Mutation(() => ShowCoreNav) - @UseGuards(AdminAuthGuards) - async admin__core_nav__edit( - @Args() args: EditAdminNavArgs, - ): Promise { - return this.service.edit(args); - } -} diff --git a/packages/backend/src/core/admin/nav/nav.module.ts b/packages/backend/src/core/admin/nav/nav.module.ts deleted file mode 100644 index d16f0658b..000000000 --- a/packages/backend/src/core/admin/nav/nav.module.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { CreateAdminNavResolver } from './create/create.resolver'; -import { CreateAdminNavService } from './create/create.service'; -import { DeleteAdminNavResolver } from './delete/delete.resolver'; -import { DeleteAdminNavService } from './delete/delete.service'; -import { ChangePositionAdminNavService } from './change_position/change_position.service'; -import { ChangePositionAdminNavResolver } from './change_position/change_position.resolver'; -import { EditAdminNavResolver } from './edit/edit.resolver'; -import { EditAdminNavService } from './edit/edit.service'; - -@Module({ - providers: [ - CreateAdminNavResolver, - CreateAdminNavService, - DeleteAdminNavResolver, - DeleteAdminNavService, - ChangePositionAdminNavService, - ChangePositionAdminNavResolver, - EditAdminNavResolver, - EditAdminNavService, - ], -}) -export class AdminNavModule {} diff --git a/packages/backend/src/core/admin/styles/editor/edit/dto/edit.args.ts b/packages/backend/src/core/admin/styles/editor/edit/dto/edit.args.ts new file mode 100644 index 000000000..d53b656cd --- /dev/null +++ b/packages/backend/src/core/admin/styles/editor/edit/dto/edit.args.ts @@ -0,0 +1,18 @@ +import { ArgsType, Field, InputType } from '@nestjs/graphql'; + +import { AllowTypeFilesEnum } from '../../../../../../providers/config'; + +@InputType() +class FilesEditAdminEditorStyles { + @Field(() => AllowTypeFilesEnum) + allow_type: AllowTypeFilesEnum; +} + +@ArgsType() +export class EditAdminEditorStylesArgs { + @Field(() => Boolean) + sticky: boolean; + + @Field(() => FilesEditAdminEditorStyles) + files: FilesEditAdminEditorStyles; +} diff --git a/packages/backend/src/core/admin/styles/editor/edit/edit.resolver.ts b/packages/backend/src/core/admin/styles/editor/edit/edit.resolver.ts new file mode 100644 index 000000000..6465a5c17 --- /dev/null +++ b/packages/backend/src/core/admin/styles/editor/edit/edit.resolver.ts @@ -0,0 +1,21 @@ +import { Args, Mutation, Resolver } from '@nestjs/graphql'; +import { UseGuards } from '@nestjs/common'; + +import { EditAdminEditorStylesService } from './edit.service'; +import { EditAdminEditorStylesArgs } from './dto/edit.args'; + +import { AdminAuthGuards } from '../../../../../utils/guards/admin-auth.guard'; +import { EditorShowCoreMiddleware } from '../../../../middleware/show/dto/show.obj'; + +@Resolver() +export class EditAdminEditorStylesResolver { + constructor(private readonly service: EditAdminEditorStylesService) {} + + @Mutation(() => EditorShowCoreMiddleware) + @UseGuards(AdminAuthGuards) + async admin__core_styles__editor__edit( + @Args() args: EditAdminEditorStylesArgs, + ): Promise { + return this.service.edit(args); + } +} diff --git a/packages/backend/src/core/admin/styles/editor/edit/edit.service.ts b/packages/backend/src/core/admin/styles/editor/edit/edit.service.ts new file mode 100644 index 000000000..19eff8be7 --- /dev/null +++ b/packages/backend/src/core/admin/styles/editor/edit/edit.service.ts @@ -0,0 +1,26 @@ +import * as fs from 'fs'; + +import { Injectable } from '@nestjs/common'; + +import { EditAdminEditorStylesArgs } from './dto/edit.args'; + +import { configPath, getConfigFile } from '../../../../../providers/config'; +import { EditorShowCoreMiddleware } from '../../../../middleware/show/dto/show.obj'; + +@Injectable() +export class EditAdminEditorStylesService { + constructor() {} + + edit(data: EditAdminEditorStylesArgs): EditorShowCoreMiddleware { + const config = getConfigFile(); + + config.editor = { + ...config.editor, + ...data, + }; + + fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); + + return config.editor; + } +} diff --git a/packages/backend/src/core/admin/styles/editor/editor.module.ts b/packages/backend/src/core/admin/styles/editor/editor.module.ts new file mode 100644 index 000000000..6bbddfaed --- /dev/null +++ b/packages/backend/src/core/admin/styles/editor/editor.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; + +import { EditAdminEditorStylesService } from './edit/edit.service'; +import { EditAdminEditorStylesResolver } from './edit/edit.resolver'; + +@Module({ + providers: [EditAdminEditorStylesService, EditAdminEditorStylesResolver], +}) +export class AdminEditorStylesModule {} diff --git a/packages/backend/src/core/admin/styles/nav/change_position/change_position.resolver.ts b/packages/backend/src/core/admin/styles/nav/change_position/change_position.resolver.ts new file mode 100644 index 000000000..c0a82ec74 --- /dev/null +++ b/packages/backend/src/core/admin/styles/nav/change_position/change_position.resolver.ts @@ -0,0 +1,20 @@ +import { Args, Mutation, Resolver } from '@nestjs/graphql'; +import { UseGuards } from '@nestjs/common'; + +import { ChangePositionAdminNavStylesService } from './change_position.service'; +import { ChangePositionAdminNavStylesArgs } from './dto/change_position.args'; + +import { AdminAuthGuards } from '../../../../../utils'; + +@Resolver() +export class ChangePositionAdminNavStylesResolver { + constructor(private readonly service: ChangePositionAdminNavStylesService) {} + + @Mutation(() => String) + @UseGuards(AdminAuthGuards) + async admin__core_nav_styles__change_position( + @Args() args: ChangePositionAdminNavStylesArgs, + ): Promise { + return this.service.changePosition(args); + } +} diff --git a/packages/backend/src/core/admin/nav/change_position/change_position.service.ts b/packages/backend/src/core/admin/styles/nav/change_position/change_position.service.ts similarity index 80% rename from packages/backend/src/core/admin/nav/change_position/change_position.service.ts rename to packages/backend/src/core/admin/styles/nav/change_position/change_position.service.ts index 3827a7066..fc373530d 100644 --- a/packages/backend/src/core/admin/nav/change_position/change_position.service.ts +++ b/packages/backend/src/core/admin/styles/nav/change_position/change_position.service.ts @@ -1,21 +1,21 @@ import { Injectable } from '@nestjs/common'; import { eq } from 'drizzle-orm'; -import { ChangePositionAdminNavArgs } from './dto/change_position.args'; +import { ChangePositionAdminNavStylesArgs } from './dto/change_position.args'; -import { DatabaseService } from '../../../../database'; -import { NotFoundError } from '../../../../errors'; -import { core_nav } from '../../../../templates/core/admin/database/schema/nav'; +import { DatabaseService } from '../../../../../database'; +import { NotFoundError } from '../../../../../errors'; +import { core_nav } from '../../../../../templates/core/admin/database/schema/nav'; @Injectable() -export class ChangePositionAdminNavService { +export class ChangePositionAdminNavStylesService { constructor(private readonly databaseService: DatabaseService) {} async changePosition({ id, index_to_move, parent_id, - }: ChangePositionAdminNavArgs): Promise { + }: ChangePositionAdminNavStylesArgs): Promise { const nav = await this.databaseService.db.query.core_nav.findFirst({ where: (table, { eq }) => eq(table.id, id), }); diff --git a/packages/backend/src/core/admin/nav/change_position/dto/change_position.args.ts b/packages/backend/src/core/admin/styles/nav/change_position/dto/change_position.args.ts similarity index 80% rename from packages/backend/src/core/admin/nav/change_position/dto/change_position.args.ts rename to packages/backend/src/core/admin/styles/nav/change_position/dto/change_position.args.ts index 9b9103286..da65b0de1 100644 --- a/packages/backend/src/core/admin/nav/change_position/dto/change_position.args.ts +++ b/packages/backend/src/core/admin/styles/nav/change_position/dto/change_position.args.ts @@ -1,7 +1,7 @@ import { ArgsType, Field, Int } from '@nestjs/graphql'; @ArgsType() -export class ChangePositionAdminNavArgs { +export class ChangePositionAdminNavStylesArgs { @Field(() => Int) id: number; diff --git a/packages/backend/src/core/admin/styles/nav/create/create.resolver.ts b/packages/backend/src/core/admin/styles/nav/create/create.resolver.ts new file mode 100644 index 000000000..f60ea1dca --- /dev/null +++ b/packages/backend/src/core/admin/styles/nav/create/create.resolver.ts @@ -0,0 +1,21 @@ +import { Args, Mutation, Resolver } from '@nestjs/graphql'; +import { UseGuards } from '@nestjs/common'; + +import { CreateAdminNavStylesService } from './create.service'; +import { CreateAdminNavStylesArgs } from './dto/create.args'; + +import { ShowCoreNav } from '../../../../nav/show/dto/show.obj'; +import { AdminAuthGuards } from '../../../../../utils'; + +@Resolver() +export class CreateAdminNavStylesResolver { + constructor(private readonly service: CreateAdminNavStylesService) {} + + @Mutation(() => ShowCoreNav) + @UseGuards(AdminAuthGuards) + async admin__core_styles__nav__create( + @Args() args: CreateAdminNavStylesArgs, + ): Promise { + return this.service.create(args); + } +} diff --git a/packages/backend/src/core/admin/nav/create/create.service.ts b/packages/backend/src/core/admin/styles/nav/create/create.service.ts similarity index 73% rename from packages/backend/src/core/admin/nav/create/create.service.ts rename to packages/backend/src/core/admin/styles/nav/create/create.service.ts index 85b5a1bac..6144972dd 100644 --- a/packages/backend/src/core/admin/nav/create/create.service.ts +++ b/packages/backend/src/core/admin/styles/nav/create/create.service.ts @@ -1,18 +1,18 @@ import { Injectable } from '@nestjs/common'; -import { CreateAdminNavArgs } from './dto/create.args'; +import { CreateAdminNavStylesArgs } from './dto/create.args'; -import { DatabaseService } from '../../../../database'; -import { ParserTextLanguageCoreHelpersService } from '../../../helpers/text_language/parser/parser.service'; -import { ShowCoreNav } from '../../../nav/show/dto/show.obj'; +import { DatabaseService } from '../../../../../database'; +import { ParserTextLanguageCoreHelpersService } from '../../../../helpers/text_language/parser/parser.service'; +import { ShowCoreNav } from '../../../../nav/show/dto/show.obj'; import { core_nav, core_nav_description, core_nav_name, -} from '../../../../templates/core/admin/database/schema/nav'; +} from '../../../../../templates/core/admin/database/schema/nav'; @Injectable() -export class CreateAdminNavService { +export class CreateAdminNavStylesService { constructor( private readonly databaseService: DatabaseService, private readonly parserTextLang: ParserTextLanguageCoreHelpersService, @@ -24,7 +24,7 @@ export class CreateAdminNavService { href, icon, name, - }: CreateAdminNavArgs): Promise { + }: CreateAdminNavStylesArgs): Promise { const theMostHighestPosition = await this.databaseService.db.query.core_nav.findFirst({ where: (table, { eq }) => eq(table.parent_id, 0), diff --git a/packages/backend/src/core/admin/nav/create/dto/create.args.ts b/packages/backend/src/core/admin/styles/nav/create/dto/create.args.ts similarity index 92% rename from packages/backend/src/core/admin/nav/create/dto/create.args.ts rename to packages/backend/src/core/admin/styles/nav/create/dto/create.args.ts index da0b26ea6..c20823d5d 100644 --- a/packages/backend/src/core/admin/nav/create/dto/create.args.ts +++ b/packages/backend/src/core/admin/styles/nav/create/dto/create.args.ts @@ -13,10 +13,10 @@ import { TextLanguageInput, TransformString, TransformTextLanguageInput, -} from '../../../../../utils'; +} from '../../../../../../utils'; @ArgsType() -export class CreateAdminNavArgs { +export class CreateAdminNavStylesArgs { @IsArray() @ValidateNested({ each: true }) @ArrayMinSize(1) diff --git a/packages/backend/src/core/admin/styles/nav/delete/delete.resolver.ts b/packages/backend/src/core/admin/styles/nav/delete/delete.resolver.ts new file mode 100644 index 000000000..efa22bae7 --- /dev/null +++ b/packages/backend/src/core/admin/styles/nav/delete/delete.resolver.ts @@ -0,0 +1,20 @@ +import { Args, Mutation, Resolver } from '@nestjs/graphql'; +import { UseGuards } from '@nestjs/common'; + +import { DeleteAdminNavStylesService } from './delete.service'; +import { DeleteAdminNavStylesArgs } from './dto/delete.args'; + +import { AdminAuthGuards } from '../../../../../utils'; + +@Resolver() +export class DeleteAdminNavStylesResolver { + constructor(private readonly service: DeleteAdminNavStylesService) {} + + @Mutation(() => String) + @UseGuards(AdminAuthGuards) + async admin__core_styles__nav__delete( + @Args() args: DeleteAdminNavStylesArgs, + ): Promise { + return this.service.delete(args); + } +} diff --git a/packages/backend/src/core/admin/nav/delete/delete.service.ts b/packages/backend/src/core/admin/styles/nav/delete/delete.service.ts similarity index 68% rename from packages/backend/src/core/admin/nav/delete/delete.service.ts rename to packages/backend/src/core/admin/styles/nav/delete/delete.service.ts index 18425947d..b1d3ccf03 100644 --- a/packages/backend/src/core/admin/nav/delete/delete.service.ts +++ b/packages/backend/src/core/admin/styles/nav/delete/delete.service.ts @@ -1,25 +1,25 @@ import { Injectable } from '@nestjs/common'; import { eq } from 'drizzle-orm'; -import { DeleteAdminNavArgs } from './dto/delete.args'; +import { DeleteAdminNavStylesArgs } from './dto/delete.args'; -import { DatabaseService } from '../../../../database'; -import { ParserTextLanguageCoreHelpersService } from '../../../helpers/text_language/parser/parser.service'; -import { NotFoundError } from '../../../../errors'; +import { DatabaseService } from '../../../../../database'; +import { ParserTextLanguageCoreHelpersService } from '../../../../helpers/text_language/parser/parser.service'; +import { NotFoundError } from '../../../../../errors'; import { core_nav, core_nav_description, core_nav_name, -} from '../../../../templates/core/admin/database/schema/nav'; +} from '../../../../../templates/core/admin/database/schema/nav'; @Injectable() -export class DeleteAdminNavService { +export class DeleteAdminNavStylesService { constructor( private readonly databaseService: DatabaseService, private readonly parserTextLang: ParserTextLanguageCoreHelpersService, ) {} - async delete({ id }: DeleteAdminNavArgs): Promise { + async delete({ id }: DeleteAdminNavStylesArgs): Promise { const nav = await this.databaseService.db.query.core_nav.findFirst({ where: (table, { eq }) => eq(table.id, id), }); diff --git a/packages/backend/src/core/admin/nav/delete/dto/delete.args.ts b/packages/backend/src/core/admin/styles/nav/delete/dto/delete.args.ts similarity index 72% rename from packages/backend/src/core/admin/nav/delete/dto/delete.args.ts rename to packages/backend/src/core/admin/styles/nav/delete/dto/delete.args.ts index b0624c089..ae67850eb 100644 --- a/packages/backend/src/core/admin/nav/delete/dto/delete.args.ts +++ b/packages/backend/src/core/admin/styles/nav/delete/dto/delete.args.ts @@ -1,7 +1,7 @@ import { ArgsType, Field, Int } from '@nestjs/graphql'; @ArgsType() -export class DeleteAdminNavArgs { +export class DeleteAdminNavStylesArgs { @Field(() => Int) id: number; } diff --git a/packages/backend/src/core/admin/styles/nav/edit/dto/edit.args.ts b/packages/backend/src/core/admin/styles/nav/edit/dto/edit.args.ts new file mode 100644 index 000000000..204540119 --- /dev/null +++ b/packages/backend/src/core/admin/styles/nav/edit/dto/edit.args.ts @@ -0,0 +1,9 @@ +import { ArgsType, Field, Int } from '@nestjs/graphql'; + +import { CreateAdminNavStylesArgs } from '../../create/dto/create.args'; + +@ArgsType() +export class EditAdminNavStylesArgs extends CreateAdminNavStylesArgs { + @Field(() => Int) + id: number; +} diff --git a/packages/backend/src/core/admin/styles/nav/edit/edit.resolver.ts b/packages/backend/src/core/admin/styles/nav/edit/edit.resolver.ts new file mode 100644 index 000000000..f9861b067 --- /dev/null +++ b/packages/backend/src/core/admin/styles/nav/edit/edit.resolver.ts @@ -0,0 +1,21 @@ +import { Args, Mutation, Resolver } from '@nestjs/graphql'; +import { UseGuards } from '@nestjs/common'; + +import { EditAdminNavStylesService } from './edit.service'; +import { EditAdminNavStylesArgs } from './dto/edit.args'; + +import { ShowCoreNav } from '../../../../nav/show/dto/show.obj'; +import { AdminAuthGuards } from '../../../../../utils'; + +@Resolver() +export class EditAdminNavStylesResolver { + constructor(private readonly service: EditAdminNavStylesService) {} + + @Mutation(() => ShowCoreNav) + @UseGuards(AdminAuthGuards) + async admin__core_styles__nav__edit( + @Args() args: EditAdminNavStylesArgs, + ): Promise { + return this.service.edit(args); + } +} diff --git a/packages/backend/src/core/admin/nav/edit/edit.service.ts b/packages/backend/src/core/admin/styles/nav/edit/edit.service.ts similarity index 73% rename from packages/backend/src/core/admin/nav/edit/edit.service.ts rename to packages/backend/src/core/admin/styles/nav/edit/edit.service.ts index 36e781ea7..522ba128e 100644 --- a/packages/backend/src/core/admin/nav/edit/edit.service.ts +++ b/packages/backend/src/core/admin/styles/nav/edit/edit.service.ts @@ -1,20 +1,20 @@ import { Injectable } from '@nestjs/common'; import { eq } from 'drizzle-orm'; -import { EditAdminNavArgs } from './dto/edit.args'; +import { EditAdminNavStylesArgs } from './dto/edit.args'; -import { DatabaseService } from '../../../../database'; -import { ParserTextLanguageCoreHelpersService } from '../../../helpers/text_language/parser/parser.service'; -import { ShowCoreNav } from '../../../nav/show/dto/show.obj'; -import { NotFoundError } from '../../../../errors'; +import { DatabaseService } from '../../../../../database'; +import { ParserTextLanguageCoreHelpersService } from '../../../../helpers/text_language/parser/parser.service'; +import { ShowCoreNav } from '../../../../nav/show/dto/show.obj'; +import { NotFoundError } from '../../../../../errors'; import { core_nav, core_nav_description, core_nav_name, -} from '../../../../templates/core/admin/database/schema/nav'; +} from '../../../../../templates/core/admin/database/schema/nav'; @Injectable() -export class EditAdminNavService { +export class EditAdminNavStylesService { constructor( private readonly databaseService: DatabaseService, private readonly parserTextLang: ParserTextLanguageCoreHelpersService, @@ -27,7 +27,7 @@ export class EditAdminNavService { icon, id, name, - }: EditAdminNavArgs): Promise { + }: EditAdminNavStylesArgs): Promise { const nav = await this.databaseService.db.query.core_nav.findFirst({ where: (table, { eq }) => eq(table.id, id), }); diff --git a/packages/backend/src/core/admin/styles/nav/nav.module.ts b/packages/backend/src/core/admin/styles/nav/nav.module.ts new file mode 100644 index 000000000..c4852fd58 --- /dev/null +++ b/packages/backend/src/core/admin/styles/nav/nav.module.ts @@ -0,0 +1,24 @@ +import { Module } from '@nestjs/common'; + +import { CreateAdminNavStylesResolver } from './create/create.resolver'; +import { CreateAdminNavStylesService } from './create/create.service'; +import { DeleteAdminNavStylesResolver } from './delete/delete.resolver'; +import { DeleteAdminNavStylesService } from './delete/delete.service'; +import { ChangePositionAdminNavStylesService } from './change_position/change_position.service'; +import { ChangePositionAdminNavStylesResolver } from './change_position/change_position.resolver'; +import { EditAdminNavStylesResolver } from './edit/edit.resolver'; +import { EditAdminNavStylesService } from './edit/edit.service'; + +@Module({ + providers: [ + CreateAdminNavStylesResolver, + CreateAdminNavStylesService, + DeleteAdminNavStylesResolver, + DeleteAdminNavStylesService, + ChangePositionAdminNavStylesService, + ChangePositionAdminNavStylesResolver, + EditAdminNavStylesResolver, + EditAdminNavStylesService, + ], +}) +export class AdminNavStylesModule {} diff --git a/packages/backend/src/core/admin/styles/styles.module.ts b/packages/backend/src/core/admin/styles/styles.module.ts new file mode 100644 index 000000000..aa227afdf --- /dev/null +++ b/packages/backend/src/core/admin/styles/styles.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; + +import { AdminNavStylesModule } from './nav/nav.module'; +import { AdminEditorStylesModule } from './editor/editor.module'; + +@Module({ + imports: [AdminNavStylesModule, AdminEditorStylesModule], +}) +export class AdminStylesModule {} diff --git a/packages/backend/src/core/middleware/show/dto/languages.obj.ts b/packages/backend/src/core/middleware/show/dto/languages.obj.ts deleted file mode 100644 index e1cddd01f..000000000 --- a/packages/backend/src/core/middleware/show/dto/languages.obj.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Field, ObjectType } from '@nestjs/graphql'; - -@ObjectType() -export class LanguagesCoreMiddleware { - @Field(() => String) - code: string; - - @Field(() => Boolean) - enabled: boolean; - - @Field(() => Boolean) - default: boolean; -} - -@ObjectType() -export class ShowCoreMiddlewareObj { - @Field(() => [LanguagesCoreMiddleware]) - languages: LanguagesCoreMiddleware[]; - - @Field(() => [String]) - plugins: string[]; -} diff --git a/packages/backend/src/core/middleware/show/dto/show.obj.ts b/packages/backend/src/core/middleware/show/dto/show.obj.ts new file mode 100644 index 000000000..b62e64d92 --- /dev/null +++ b/packages/backend/src/core/middleware/show/dto/show.obj.ts @@ -0,0 +1,58 @@ +import { Field, ObjectType, registerEnumType } from '@nestjs/graphql'; + +import { AllowTypeFilesEnum } from '../../../../providers/config'; + +registerEnumType(AllowTypeFilesEnum, { + name: 'AllowTypeFilesEnum', +}); + +@ObjectType() +export class RebuildRequiredEditorShowCoreMiddleware { + @Field(() => Boolean) + langs: boolean; + + @Field(() => Boolean) + plugins: boolean; +} + +@ObjectType() +export class FilesEditorShowCoreMiddleware { + @Field(() => AllowTypeFilesEnum) + allow_type: AllowTypeFilesEnum; +} + +@ObjectType() +export class EditorShowCoreMiddleware { + @Field(() => Boolean) + sticky: boolean; + + @Field(() => FilesEditorShowCoreMiddleware) + files: FilesEditorShowCoreMiddleware; +} + +@ObjectType() +export class LanguagesCoreMiddleware { + @Field(() => String) + code: string; + + @Field(() => Boolean) + enabled: boolean; + + @Field(() => Boolean) + default: boolean; +} + +@ObjectType() +export class ShowCoreMiddlewareObj { + @Field(() => [LanguagesCoreMiddleware]) + languages: LanguagesCoreMiddleware[]; + + @Field(() => [String]) + plugins: string[]; + + @Field(() => EditorShowCoreMiddleware) + editor: EditorShowCoreMiddleware; + + @Field(() => RebuildRequiredEditorShowCoreMiddleware) + rebuild_required: RebuildRequiredEditorShowCoreMiddleware; +} diff --git a/packages/backend/src/core/middleware/show/show.resolver.ts b/packages/backend/src/core/middleware/show/show.resolver.ts index e828303aa..4b750445b 100644 --- a/packages/backend/src/core/middleware/show/show.resolver.ts +++ b/packages/backend/src/core/middleware/show/show.resolver.ts @@ -1,7 +1,7 @@ import { Query, Resolver } from '@nestjs/graphql'; import { ShowCoreMiddlewareService } from './show.service'; -import { ShowCoreMiddlewareObj } from './dto/languages.obj'; +import { ShowCoreMiddlewareObj } from './dto/show.obj'; @Resolver() export class ShowCoreMiddlewareResolver { @@ -9,6 +9,6 @@ export class ShowCoreMiddlewareResolver { @Query(() => ShowCoreMiddlewareObj) async core_middleware__show(): Promise { - return this.service.languages(); + return this.service.show(); } } diff --git a/packages/backend/src/core/middleware/show/show.service.ts b/packages/backend/src/core/middleware/show/show.service.ts index aad9170d9..085f682f0 100644 --- a/packages/backend/src/core/middleware/show/show.service.ts +++ b/packages/backend/src/core/middleware/show/show.service.ts @@ -2,15 +2,14 @@ import { readdir } from 'fs/promises'; import { Injectable } from '@nestjs/common'; -import { ShowCoreMiddlewareObj } from './dto/languages.obj'; +import { ShowCoreMiddlewareObj } from './dto/show.obj'; import { ABSOLUTE_PATHS_BACKEND, getConfigFile } from '../../..'; @Injectable() export class ShowCoreMiddlewareService { - async languages(): Promise { + async show(): Promise { const config = getConfigFile(); - const plugins = await readdir(ABSOLUTE_PATHS_BACKEND.plugins); return { @@ -19,6 +18,7 @@ export class ShowCoreMiddlewareService { 'admin', ...plugins.filter(plugin => !['plugins.module.ts'].includes(plugin)), ], + ...config, }; } } diff --git a/packages/backend/src/providers/config.ts b/packages/backend/src/providers/config.ts index 8bce69ff6..fcae65394 100644 --- a/packages/backend/src/providers/config.ts +++ b/packages/backend/src/providers/config.ts @@ -1,10 +1,17 @@ import * as fs from 'fs'; import { join } from 'path'; +export enum AllowTypeFilesEnum { + all = 'all', + images_videos = 'images_videos', + images = 'images', + none = 'none', +} + export interface ConfigType { editor: { files: { - allow_type: 'all' | 'images_videos' | 'images' | 'none'; + allow_type: AllowTypeFilesEnum; }; sticky: boolean; }; @@ -29,10 +36,46 @@ export interface ConfigType { }; } +export const DEFAULT_CONFIG_DATA: ConfigType = { + rebuild_required: { + langs: false, + plugins: false, + }, + editor: { + sticky: true, + files: { + allow_type: AllowTypeFilesEnum.all, + }, + }, + settings: { + general: { + site_name: 'VitNode Community', + site_short_name: 'VitNode', + }, + email: { + color_primary: 'hsl(220, 74%, 50%)', + color_primary_foreground: 'hsl(210, 40%, 98%)', + }, + }, + langs: [ + { + code: 'en', + enabled: true, + default: true, + }, + { + code: 'pl', + enabled: true, + default: false, + }, + ], +}; + export const configPath = join( process.cwd(), - '..', - 'frontend', + 'src', + 'plugins', + 'core', 'utils', 'config.json', ); diff --git a/packages/frontend/package.json b/packages/frontend/package.json index e00426771..0241ca6dd 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -10,9 +10,6 @@ "url": "git+https://github.com/aXenDeveloper/VitNode.git", "directory": "packages/frontend" }, - "bin": { - "vitnode-frontend": "dist/scripts/setup.js" - }, "exports": { "./middleware": { "types": "./src/middleware.ts", @@ -69,7 +66,6 @@ }, "scripts": { "build": "tsc", - "build:scripts": "tsup", "dev": "tsc -w", "lint": "eslint .", "lint:fix": "eslint . --fix", @@ -91,7 +87,6 @@ "graphql-tag": "^2.12.6", "tailwind-merge": "^2.3.0", "ts-node": "^10.9.2", - "tsup": "^8.1.0", "typescript": "^5.5.2" }, "dependencies": { diff --git a/packages/frontend/scripts/helpers/update-object.ts b/packages/frontend/scripts/helpers/update-object.ts deleted file mode 100644 index b415a9832..000000000 --- a/packages/frontend/scripts/helpers/update-object.ts +++ /dev/null @@ -1,33 +0,0 @@ -export function updateObject>( - config: T, - defaultData: T, -): T { - const updatedConfig = config; - for (const key in defaultData) { - if (Array.isArray(defaultData[key])) { - // If the key corresponds to an array and it's not empty, don't edit - if (!config[key] || config[key].length === 0) { - updatedConfig[key] = [] as any; - } - } else if ( - typeof defaultData[key] === 'object' && - defaultData[key] !== null - ) { - // Handle nested objects - if (!config[key]) { - updatedConfig[key] = {} as T[Extract]; - } - updatedConfig[key] = updateObject( - (config[key] || {}) as T[Extract], - defaultData[key], - ); - } else { - // Handle primitive values - if (!config[key]) { - updatedConfig[key] = defaultData[key]; - } - } - } - - return updatedConfig; -} diff --git a/packages/frontend/scripts/setup.ts b/packages/frontend/scripts/setup.ts deleted file mode 100755 index b33a67d0b..000000000 --- a/packages/frontend/scripts/setup.ts +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env node -import * as fs from 'fs'; -import { join } from 'path'; - -import { - DEFAULT_CONFIG_DATA, - configPath, - getConfigFile, -} from '../src/helpers/config'; -import { updateObject } from './helpers/update-object'; - -/* eslint-disable no-console */ - -const generateConfigFile = async () => { - const pathToFolder = join(process.cwd(), 'config'); - if (!fs.existsSync(pathToFolder)) { - fs.mkdirSync(pathToFolder, { recursive: true }); - } - - if (!fs.existsSync(configPath)) { - fs.writeFileSync( - configPath, - JSON.stringify( - { - ...DEFAULT_CONFIG_DATA, - lang: [ - { code: 'en', enabled: true }, - { code: 'pl', enabled: true }, - ], - }, - null, - 2, - ), - 'utf8', - ); - - console.log( - '\x1b[34m%s\x1b[0m', - '[VitNode]', - 'Config file created successfully.', - ); - process.exit(0); - } - - console.log( - '\x1b[34m%s\x1b[0m', - '[VitNode]', - 'Config file already exists. Updating...', - ); - - const config = await getConfigFile(); - const updatedConfig = updateObject( - { - ...config, - rebuild_required: { - langs: false, - plugins: false, - }, - }, - DEFAULT_CONFIG_DATA, - ); - - fs.writeFileSync(configPath, JSON.stringify(updatedConfig, null, 2), 'utf8'); - - console.log( - '\x1b[34m%s\x1b[0m', - '[VitNode]', - 'Config file updated successfully.', - ); -}; - -if (process.argv[2] === 'init') { - generateConfigFile(); -} diff --git a/packages/frontend/src/graphql/get-global-data.ts b/packages/frontend/src/graphql/get-global-data.ts new file mode 100644 index 000000000..540e61966 --- /dev/null +++ b/packages/frontend/src/graphql/get-global-data.ts @@ -0,0 +1,11 @@ +import { fetcher } from './fetcher'; +import { Core_Global, Core_GlobalQuery } from './graphql'; + +export const getGlobalData = async () => { + const { data } = await fetcher({ + query: Core_Global, + cache: 'force-cache', + }); + + return data; +}; diff --git a/packages/frontend/src/graphql/get-session-data.ts b/packages/frontend/src/graphql/get-session-data.ts index d600a77db..a3ee4640d 100644 --- a/packages/frontend/src/graphql/get-session-data.ts +++ b/packages/frontend/src/graphql/get-session-data.ts @@ -14,8 +14,5 @@ export const getSessionData = async () => { cache: 'force-cache', }); - return { - data, - default_plugin: data.core_sessions__authorization.plugin_default, - }; + return data; }; diff --git a/packages/frontend/src/graphql/graphql.ts b/packages/frontend/src/graphql/graphql.ts index 178155390..91617812e 100644 --- a/packages/frontend/src/graphql/graphql.ts +++ b/packages/frontend/src/graphql/graphql.ts @@ -17,6 +17,14 @@ export type Scalars = { Upload: { input: any; output: any; } }; +export const AllowTypeFilesEnum = { + all: 'all', + images: 'images', + images_videos: 'images_videos', + none: 'none' +} as const; + +export type AllowTypeFilesEnum = typeof AllowTypeFilesEnum[keyof typeof AllowTypeFilesEnum]; export type AuthorizationAdminSessionsObj = { __typename?: 'AuthorizationAdminSessionsObj'; nav: Array; @@ -121,6 +129,12 @@ export type EditAdminSettingsObj = { site_name: Scalars['String']['output']; }; +export type EditorShowCoreMiddleware = { + __typename?: 'EditorShowCoreMiddleware'; + files: FilesEditorShowCoreMiddleware; + sticky: Scalars['Boolean']['output']; +}; + export type FilesAdminPluginsObj = { __typename?: 'FilesAdminPluginsObj'; admin_pages: Scalars['Int']['output']; @@ -140,6 +154,15 @@ export type FilesAuthorizationCoreSessions = { total_max_storage: Scalars['Int']['output']; }; +export type FilesEditAdminEditorStyles = { + allow_type: AllowTypeFilesEnum | `${AllowTypeFilesEnum}`; +}; + +export type FilesEditorShowCoreMiddleware = { + __typename?: 'FilesEditorShowCoreMiddleware'; + allow_type: AllowTypeFilesEnum | `${AllowTypeFilesEnum}`; +}; + export type GroupUser = { __typename?: 'GroupUser'; id: Scalars['Int']['output']; @@ -202,10 +225,7 @@ export type Mutation = { admin__core_main_settings__edit: EditAdminSettingsObj; admin__core_manifest_metadata__edit: ShowAdminManifestMetadataObj; admin__core_members__edit: EditAdminMembersObj; - admin__core_nav__change_position: Scalars['String']['output']; - admin__core_nav__create: ShowCoreNav; - admin__core_nav__delete: Scalars['String']['output']; - admin__core_nav__edit: ShowCoreNav; + admin__core_nav_styles__change_position: Scalars['String']['output']; admin__core_plugins__create: ShowAdminPlugins; admin__core_plugins__delete: Scalars['String']['output']; admin__core_plugins__download: Scalars['String']['output']; @@ -219,6 +239,10 @@ export type Mutation = { admin__core_staff_administrators__delete: Scalars['String']['output']; admin__core_staff_moderators__create: ShowAdminStaffModerators; admin__core_staff_moderators__delete: Scalars['String']['output']; + admin__core_styles__editor__edit: EditorShowCoreMiddleware; + admin__core_styles__nav__create: ShowCoreNav; + admin__core_styles__nav__delete: Scalars['String']['output']; + admin__core_styles__nav__edit: ShowCoreNav; admin__core_theme_editor__edit: Scalars['String']['output']; admin__install__create_database: Scalars['String']['output']; admin_sessions__sign_out: Scalars['String']['output']; @@ -257,7 +281,7 @@ export type MutationAdmin__Core_Email_Settings__EditArgs = { export type MutationAdmin__Core_Email_Settings__TestArgs = { from: Scalars['String']['input']; message: Scalars['String']['input']; - previewText?: InputMaybe; + preview_text?: InputMaybe; subject: Scalars['String']['input']; to: Scalars['String']['input']; }; @@ -346,37 +370,13 @@ export type MutationAdmin__Core_Members__EditArgs = { }; -export type MutationAdmin__Core_Nav__Change_PositionArgs = { +export type MutationAdmin__Core_Nav_Styles__Change_PositionArgs = { id: Scalars['Int']['input']; index_to_move: Scalars['Int']['input']; parent_id: Scalars['Int']['input']; }; -export type MutationAdmin__Core_Nav__CreateArgs = { - description: Array; - external: Scalars['Boolean']['input']; - href: Scalars['String']['input']; - icon?: InputMaybe; - name: Array; -}; - - -export type MutationAdmin__Core_Nav__DeleteArgs = { - id: Scalars['Int']['input']; -}; - - -export type MutationAdmin__Core_Nav__EditArgs = { - description: Array; - external: Scalars['Boolean']['input']; - href: Scalars['String']['input']; - icon?: InputMaybe; - id: Scalars['Int']['input']; - name: Array; -}; - - export type MutationAdmin__Core_Plugins__CreateArgs = { author: Scalars['String']['input']; author_url?: InputMaybe; @@ -475,6 +475,36 @@ export type MutationAdmin__Core_Staff_Moderators__DeleteArgs = { }; +export type MutationAdmin__Core_Styles__Editor__EditArgs = { + files: FilesEditAdminEditorStyles; + sticky: Scalars['Boolean']['input']; +}; + + +export type MutationAdmin__Core_Styles__Nav__CreateArgs = { + description: Array; + external: Scalars['Boolean']['input']; + href: Scalars['String']['input']; + icon?: InputMaybe; + name: Array; +}; + + +export type MutationAdmin__Core_Styles__Nav__DeleteArgs = { + id: Scalars['Int']['input']; +}; + + +export type MutationAdmin__Core_Styles__Nav__EditArgs = { + description: Array; + external: Scalars['Boolean']['input']; + href: Scalars['String']['input']; + icon?: InputMaybe; + id: Scalars['Int']['input']; + name: Array; +}; + + export type MutationAdmin__Core_Theme_Editor__EditArgs = { colors: ColorsEditAdminThemeEditor; }; @@ -687,6 +717,12 @@ export type QueryCore_Nav__ShowArgs = { last?: InputMaybe; }; +export type RebuildRequiredEditorShowCoreMiddleware = { + __typename?: 'RebuildRequiredEditorShowCoreMiddleware'; + langs: Scalars['Boolean']['output']; + plugins: Scalars['Boolean']['output']; +}; + export type ShowAdminEmailSettingsServiceObj = { __typename?: 'ShowAdminEmailSettingsServiceObj'; color_primary: Scalars['String']['output']; @@ -1019,8 +1055,10 @@ export const ShowCoreMembersSortingColumnEnum = { export type ShowCoreMembersSortingColumnEnum = typeof ShowCoreMembersSortingColumnEnum[keyof typeof ShowCoreMembersSortingColumnEnum]; export type ShowCoreMiddlewareObj = { __typename?: 'ShowCoreMiddlewareObj'; + editor: EditorShowCoreMiddleware; languages: Array; plugins: Array; + rebuild_required: RebuildRequiredEditorShowCoreMiddleware; }; export type ShowCoreNav = { @@ -1411,16 +1449,24 @@ export type Admin__Core_Email_Settings__TestMutationVariables = Exact<{ export type Admin__Core_Email_Settings__TestMutation = { __typename?: 'Mutation', admin__core_email_settings__test: string }; -export type Admin__Core_Nav__Change_PositionMutationVariables = Exact<{ +export type Admin__Core_Styles__Editor__EditMutationVariables = Exact<{ + files: FilesEditAdminEditorStyles; + sticky: Scalars['Boolean']['input']; +}>; + + +export type Admin__Core_Styles__Editor__EditMutation = { __typename?: 'Mutation', admin__core_styles__editor__edit: { __typename?: 'EditorShowCoreMiddleware', sticky: boolean } }; + +export type Admin__Core_Nav_Styles__Change_PositionMutationVariables = Exact<{ id: Scalars['Int']['input']; indexToMove: Scalars['Int']['input']; parentId: Scalars['Int']['input']; }>; -export type Admin__Core_Nav__Change_PositionMutation = { __typename?: 'Mutation', admin__core_nav__change_position: string }; +export type Admin__Core_Nav_Styles__Change_PositionMutation = { __typename?: 'Mutation', admin__core_nav_styles__change_position: string }; -export type Admin__Core_Nav__CreateMutationVariables = Exact<{ +export type Admin__Core_Styles__Nav__CreateMutationVariables = Exact<{ description: Array | TextLanguageInput; external: Scalars['Boolean']['input']; href: Scalars['String']['input']; @@ -1429,16 +1475,16 @@ export type Admin__Core_Nav__CreateMutationVariables = Exact<{ }>; -export type Admin__Core_Nav__CreateMutation = { __typename?: 'Mutation', admin__core_nav__create: { __typename?: 'ShowCoreNav', id: number, name: Array<{ __typename?: 'TextLanguage', language_code: string, value: string }> } }; +export type Admin__Core_Styles__Nav__CreateMutation = { __typename?: 'Mutation', admin__core_styles__nav__create: { __typename?: 'ShowCoreNav', id: number, name: Array<{ __typename?: 'TextLanguage', language_code: string, value: string }> } }; -export type Admin__Core_Nav__DeleteMutationVariables = Exact<{ +export type Admin__Core_Styles__Nav__DeleteMutationVariables = Exact<{ id: Scalars['Int']['input']; }>; -export type Admin__Core_Nav__DeleteMutation = { __typename?: 'Mutation', admin__core_nav__delete: string }; +export type Admin__Core_Styles__Nav__DeleteMutation = { __typename?: 'Mutation', admin__core_styles__nav__delete: string }; -export type Admin__Core_Nav__EditMutationVariables = Exact<{ +export type Admin__Core_Styles__Nav__EditMutationVariables = Exact<{ description: Array | TextLanguageInput; external: Scalars['Boolean']['input']; href: Scalars['String']['input']; @@ -1448,7 +1494,7 @@ export type Admin__Core_Nav__EditMutationVariables = Exact<{ }>; -export type Admin__Core_Nav__EditMutation = { __typename?: 'Mutation', admin__core_nav__edit: { __typename?: 'ShowCoreNav', id: number, name: Array<{ __typename?: 'TextLanguage', language_code: string, value: string }> } }; +export type Admin__Core_Styles__Nav__EditMutation = { __typename?: 'Mutation', admin__core_styles__nav__edit: { __typename?: 'ShowCoreNav', id: number, name: Array<{ __typename?: 'TextLanguage', language_code: string, value: string }> } }; export type Admin__Core_Theme_Editor__EditMutationVariables = Exact<{ colors: ColorsEditAdminThemeEditor; @@ -1668,10 +1714,10 @@ export type Core_Theme_Editor__ShowQueryVariables = Exact<{ [key: string]: never export type Core_Theme_Editor__ShowQuery = { __typename?: 'Query', core_theme_editor__show: { __typename?: 'ShowCoreThemeEditorObj', colors: { __typename?: 'ColorsShowCoreThemeEditor', background: { __typename?: 'ThemeVariable', dark: { __typename?: 'HslColor', h: number, l: number, s: number }, light: { __typename?: 'HslColor', h: number, l: number, s: number } }, primary: { __typename?: 'ThemeVariable', dark: { __typename?: 'HslColor', h: number, l: number, s: number }, light: { __typename?: 'HslColor', h: number, l: number, s: number } }, secondary: { __typename?: 'ThemeVariable', dark: { __typename?: 'HslColor', h: number, l: number, s: number }, light: { __typename?: 'HslColor', h: number, l: number, s: number } }, primary_foreground: { __typename?: 'ThemeVariable', dark: { __typename?: 'HslColor', h: number, l: number, s: number }, light: { __typename?: 'HslColor', h: number, l: number, s: number } }, secondary_foreground: { __typename?: 'ThemeVariable', dark: { __typename?: 'HslColor', h: number, l: number, s: number }, light: { __typename?: 'HslColor', h: number, l: number, s: number } }, destructive: { __typename?: 'ThemeVariable', dark: { __typename?: 'HslColor', h: number, l: number, s: number }, light: { __typename?: 'HslColor', h: number, l: number, s: number } }, destructive_foreground: { __typename?: 'ThemeVariable', dark: { __typename?: 'HslColor', h: number, l: number, s: number }, light: { __typename?: 'HslColor', h: number, l: number, s: number } }, cover: { __typename?: 'ThemeVariable', dark: { __typename?: 'HslColor', h: number, l: number, s: number }, light: { __typename?: 'HslColor', h: number, l: number, s: number } }, cover_foreground: { __typename?: 'ThemeVariable', dark: { __typename?: 'HslColor', h: number, l: number, s: number }, light: { __typename?: 'HslColor', h: number, l: number, s: number } }, muted: { __typename?: 'ThemeVariable', dark: { __typename?: 'HslColor', h: number, l: number, s: number }, light: { __typename?: 'HslColor', h: number, l: number, s: number } }, muted_foreground: { __typename?: 'ThemeVariable', dark: { __typename?: 'HslColor', h: number, l: number, s: number }, light: { __typename?: 'HslColor', h: number, l: number, s: number } }, accent: { __typename?: 'ThemeVariable', dark: { __typename?: 'HslColor', h: number, l: number, s: number }, light: { __typename?: 'HslColor', h: number, l: number, s: number } }, accent_foreground: { __typename?: 'ThemeVariable', dark: { __typename?: 'HslColor', h: number, l: number, s: number }, light: { __typename?: 'HslColor', h: number, l: number, s: number } }, card: { __typename?: 'ThemeVariable', dark: { __typename?: 'HslColor', h: number, l: number, s: number }, light: { __typename?: 'HslColor', h: number, l: number, s: number } }, border: { __typename?: 'ThemeVariable', dark: { __typename?: 'HslColor', h: number, l: number, s: number }, light: { __typename?: 'HslColor', h: number, l: number, s: number } } } } }; -export type Core_MiddlewareQueryVariables = Exact<{ [key: string]: never; }>; +export type Core_GlobalQueryVariables = Exact<{ [key: string]: never; }>; -export type Core_MiddlewareQuery = { __typename?: 'Query', core_languages__show: { __typename?: 'ShowCoreLanguagesObj', edges: Array<{ __typename?: 'ShowCoreLanguages', default: boolean, code: string, id: number, name: string, timezone: string, enabled: boolean, locale: string, allow_in_input: boolean, time_24: boolean }> }, core_plugins__show: Array<{ __typename?: 'ShowCorePluginsObj', code: string }>, core_settings__show: { __typename?: 'ShowSettingsObj', site_name: string, site_copyright: Array<{ __typename?: 'TextLanguage', language_code: string, value: string }>, site_description: Array<{ __typename?: 'TextLanguage', language_code: string, value: string }> } }; +export type Core_GlobalQuery = { __typename?: 'Query', core_languages__show: { __typename?: 'ShowCoreLanguagesObj', edges: Array<{ __typename?: 'ShowCoreLanguages', default: boolean, code: string, id: number, name: string, timezone: string, enabled: boolean, locale: string, allow_in_input: boolean, time_24: boolean }> }, core_plugins__show: Array<{ __typename?: 'ShowCorePluginsObj', code: string }>, core_settings__show: { __typename?: 'ShowSettingsObj', site_name: string, site_short_name: string, site_copyright: Array<{ __typename?: 'TextLanguage', language_code: string, value: string }>, site_description: Array<{ __typename?: 'TextLanguage', language_code: string, value: string }> }, core_middleware__show: { __typename?: 'ShowCoreMiddlewareObj', editor: { __typename?: 'EditorShowCoreMiddleware', sticky: boolean, files: { __typename?: 'FilesEditorShowCoreMiddleware', allow_type: AllowTypeFilesEnum } }, rebuild_required: { __typename?: 'RebuildRequiredEditorShowCoreMiddleware', langs: boolean, plugins: boolean } } }; export type Core_Middleware__ShowQueryVariables = Exact<{ [key: string]: never; }>; @@ -1985,22 +2031,29 @@ export const Admin__Core_Email_Settings__Test = gql` from: $from message: $message subject: $subject - previewText: $previewText + preview_text: $previewText ) } `; -export const Admin__Core_Nav__Change_Position = gql` - mutation Admin__core_nav__change_position($id: Int!, $indexToMove: Int!, $parentId: Int!) { - admin__core_nav__change_position( +export const Admin__Core_Styles__Editor__Edit = gql` + mutation Admin__core_styles__editor__edit($files: FilesEditAdminEditorStyles!, $sticky: Boolean!) { + admin__core_styles__editor__edit(files: $files, sticky: $sticky) { + sticky + } +} + `; +export const Admin__Core_Nav_Styles__Change_Position = gql` + mutation Admin__core_nav_styles__change_position($id: Int!, $indexToMove: Int!, $parentId: Int!) { + admin__core_nav_styles__change_position( id: $id index_to_move: $indexToMove parent_id: $parentId ) } `; -export const Admin__Core_Nav__Create = gql` - mutation Admin__core_nav__create($description: [TextLanguageInput!]!, $external: Boolean!, $href: String!, $name: [TextLanguageInput!]!, $icon: String) { - admin__core_nav__create( +export const Admin__Core_Styles__Nav__Create = gql` + mutation Admin__core_styles__nav__create($description: [TextLanguageInput!]!, $external: Boolean!, $href: String!, $name: [TextLanguageInput!]!, $icon: String) { + admin__core_styles__nav__create( description: $description external: $external href: $href @@ -2015,14 +2068,14 @@ export const Admin__Core_Nav__Create = gql` } } `; -export const Admin__Core_Nav__Delete = gql` - mutation Admin__core_nav__delete($id: Int!) { - admin__core_nav__delete(id: $id) +export const Admin__Core_Styles__Nav__Delete = gql` + mutation Admin__core_styles__nav__delete($id: Int!) { + admin__core_styles__nav__delete(id: $id) } `; -export const Admin__Core_Nav__Edit = gql` - mutation Admin__core_nav__edit($description: [TextLanguageInput!]!, $external: Boolean!, $href: String!, $id: Int!, $name: [TextLanguageInput!]!, $icon: String) { - admin__core_nav__edit( +export const Admin__Core_Styles__Nav__Edit = gql` + mutation Admin__core_styles__nav__edit($description: [TextLanguageInput!]!, $external: Boolean!, $href: String!, $id: Int!, $name: [TextLanguageInput!]!, $icon: String) { + admin__core_styles__nav__edit( description: $description external: $external href: $href @@ -2803,8 +2856,8 @@ export const Core_Theme_Editor__Show = gql` } } `; -export const Core_Middleware = gql` - query Core_middleware { +export const Core_Global = gql` + query Core_global { core_languages__show { edges { default @@ -2831,6 +2884,19 @@ export const Core_Middleware = gql` value } site_name + site_short_name + } + core_middleware__show { + editor { + files { + allow_type + } + sticky + } + rebuild_required { + langs + plugins + } } } `; diff --git a/packages/frontend/src/graphql/mutations/admin/settings/email/admin__core_email_settings__test.gql b/packages/frontend/src/graphql/mutations/admin/settings/email/admin__core_email_settings__test.gql index e8889bb51..6272ea80b 100644 --- a/packages/frontend/src/graphql/mutations/admin/settings/email/admin__core_email_settings__test.gql +++ b/packages/frontend/src/graphql/mutations/admin/settings/email/admin__core_email_settings__test.gql @@ -10,6 +10,6 @@ mutation Admin__core_email_settings__test( from: $from message: $message subject: $subject - previewText: $previewText + preview_text: $previewText ) } diff --git a/packages/frontend/src/graphql/mutations/admin/styles/editor/admin__core_styles__editor__edit.gql b/packages/frontend/src/graphql/mutations/admin/styles/editor/admin__core_styles__editor__edit.gql new file mode 100644 index 000000000..1dd56bf51 --- /dev/null +++ b/packages/frontend/src/graphql/mutations/admin/styles/editor/admin__core_styles__editor__edit.gql @@ -0,0 +1,8 @@ +mutation Admin__core_styles__editor__edit( + $files: FilesEditAdminEditorStyles! + $sticky: Boolean! +) { + admin__core_styles__editor__edit(files: $files, sticky: $sticky) { + sticky + } +} diff --git a/packages/frontend/src/graphql/mutations/admin/styles/nav/core_nav__admin__change_position.gql b/packages/frontend/src/graphql/mutations/admin/styles/nav/core_nav__admin__change_position.gql index 9fbfb30dd..b298980c9 100644 --- a/packages/frontend/src/graphql/mutations/admin/styles/nav/core_nav__admin__change_position.gql +++ b/packages/frontend/src/graphql/mutations/admin/styles/nav/core_nav__admin__change_position.gql @@ -1,9 +1,9 @@ -mutation Admin__core_nav__change_position( +mutation Admin__core_nav_styles__change_position( $id: Int! $indexToMove: Int! $parentId: Int! ) { - admin__core_nav__change_position( + admin__core_nav_styles__change_position( id: $id index_to_move: $indexToMove parent_id: $parentId diff --git a/packages/frontend/src/graphql/mutations/admin/styles/nav/core_nav__admin__create.gql b/packages/frontend/src/graphql/mutations/admin/styles/nav/core_nav__admin__create.gql index 338ddd9db..839b090f8 100644 --- a/packages/frontend/src/graphql/mutations/admin/styles/nav/core_nav__admin__create.gql +++ b/packages/frontend/src/graphql/mutations/admin/styles/nav/core_nav__admin__create.gql @@ -1,11 +1,11 @@ -mutation Admin__core_nav__create( +mutation Admin__core_styles__nav__create( $description: [TextLanguageInput!]! $external: Boolean! $href: String! $name: [TextLanguageInput!]! $icon: String ) { - admin__core_nav__create( + admin__core_styles__nav__create( description: $description external: $external href: $href diff --git a/packages/frontend/src/graphql/mutations/admin/styles/nav/core_nav__admin__delete.gql b/packages/frontend/src/graphql/mutations/admin/styles/nav/core_nav__admin__delete.gql index 3d7d8d96d..a26f2bb6d 100644 --- a/packages/frontend/src/graphql/mutations/admin/styles/nav/core_nav__admin__delete.gql +++ b/packages/frontend/src/graphql/mutations/admin/styles/nav/core_nav__admin__delete.gql @@ -1,3 +1,3 @@ -mutation Admin__core_nav__delete($id: Int!) { - admin__core_nav__delete(id: $id) +mutation Admin__core_styles__nav__delete($id: Int!) { + admin__core_styles__nav__delete(id: $id) } diff --git a/packages/frontend/src/graphql/mutations/admin/styles/nav/core_nav__admin__edit.gql b/packages/frontend/src/graphql/mutations/admin/styles/nav/core_nav__admin__edit.gql index d88720fdb..f4a402853 100644 --- a/packages/frontend/src/graphql/mutations/admin/styles/nav/core_nav__admin__edit.gql +++ b/packages/frontend/src/graphql/mutations/admin/styles/nav/core_nav__admin__edit.gql @@ -1,4 +1,4 @@ -mutation Admin__core_nav__edit( +mutation Admin__core_styles__nav__edit( $description: [TextLanguageInput!]! $external: Boolean! $href: String! @@ -6,7 +6,7 @@ mutation Admin__core_nav__edit( $name: [TextLanguageInput!]! $icon: String ) { - admin__core_nav__edit( + admin__core_styles__nav__edit( description: $description external: $external href: $href diff --git a/packages/frontend/src/graphql/queries/core_middleware.gql b/packages/frontend/src/graphql/queries/core_global.gql similarity index 65% rename from packages/frontend/src/graphql/queries/core_middleware.gql rename to packages/frontend/src/graphql/queries/core_global.gql index b129b54ae..838794774 100644 --- a/packages/frontend/src/graphql/queries/core_middleware.gql +++ b/packages/frontend/src/graphql/queries/core_global.gql @@ -1,4 +1,4 @@ -query Core_middleware { +query Core_global { core_languages__show { edges { default @@ -25,5 +25,18 @@ query Core_middleware { value } site_name + site_short_name + } + core_middleware__show { + editor { + files { + allow_type + } + sticky + } + rebuild_required { + langs + plugins + } } } diff --git a/packages/frontend/src/helpers/config.ts b/packages/frontend/src/helpers/config.ts deleted file mode 100644 index fdade2995..000000000 --- a/packages/frontend/src/helpers/config.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { join } from 'path'; -import * as fs from 'fs'; - -import { ConfigType } from 'vitnode-shared'; - -export const DEFAULT_CONFIG_DATA: ConfigType = { - rebuild_required: { - langs: false, - plugins: false, - }, - editor: { - sticky: true, - files: { - allow_type: 'all', - }, - }, - settings: { - general: { - site_name: 'VitNode Community', - site_short_name: 'VitNode', - }, - email: { - color_primary: 'hsl(220, 74%, 50%)', - color_primary_foreground: 'hsl(210, 40%, 98%)', - }, - }, - langs: [ - { - code: 'en', - enabled: true, - default: true, - }, - { - code: 'pl', - enabled: true, - default: false, - }, - ], -}; - -export const configPath = join(process.cwd(), 'utils', 'config.json'); - -export const getConfigFile = async () => { - const file = await fs.promises.readFile(configPath, 'utf8'); - - return JSON.parse(file) as ConfigType; -}; diff --git a/packages/frontend/src/hooks/use-globals.ts b/packages/frontend/src/hooks/use-globals.ts index 413b17a98..1c743b221 100644 --- a/packages/frontend/src/hooks/use-globals.ts +++ b/packages/frontend/src/hooks/use-globals.ts @@ -1,18 +1,19 @@ -import { ConfigType } from 'vitnode-shared'; import * as React from 'react'; -import { Core_MiddlewareQuery } from '../graphql/graphql'; +import { Core_GlobalQuery } from '../graphql/graphql'; interface Args { - config: ConfigType; + config: Core_GlobalQuery['core_middleware__show']; defaultLanguage: string; - languages: Core_MiddlewareQuery['core_languages__show']['edges']; + languages: Core_GlobalQuery['core_languages__show']['edges']; + settings: Core_GlobalQuery['core_settings__show']; } export const GlobalsContext = React.createContext({ languages: [], defaultLanguage: '', - config: {} as ConfigType, + settings: {} as Core_GlobalQuery['core_settings__show'], + config: {} as Core_GlobalQuery['core_middleware__show'], }); export const useGlobals = () => React.useContext(GlobalsContext); diff --git a/packages/frontend/src/views/admin/views/core/plugins/views/dev/layout/layout.tsx b/packages/frontend/src/views/admin/views/core/plugins/views/dev/layout/layout.tsx index 7aa71afda..687dc59da 100644 --- a/packages/frontend/src/views/admin/views/core/plugins/views/dev/layout/layout.tsx +++ b/packages/frontend/src/views/admin/views/core/plugins/views/dev/layout/layout.tsx @@ -12,8 +12,8 @@ import { Badge } from '../../../../../../../../components/ui/badge'; import { DateFormat } from '../../../../../../../../components/date-format'; import { Tabs, TabsTrigger } from '../../../../../../../../components/ui/tabs'; import { Card } from '../../../../../../../../components/ui/card'; -import { getConfigFile } from '../../../../../../../../helpers/config'; import { CONFIG } from '../../../../../../../../helpers/config-with-env'; +import { getGlobalData } from '../../../../../../../../graphql/get-global-data'; export interface DevPluginAdminLayoutProps { children: React.ReactNode; @@ -28,13 +28,13 @@ export async function generateMetadataDevPluginAdminLayout({ const [t, tCore, config] = await Promise.all([ getTranslations('admin'), getTranslations('core.admin'), - getConfigFile(), + getGlobalData(), ]); const { data } = await getPluginDataAdmin({ code }); if (!data || data.admin__core_plugins__show.edges.length === 0) return {}; - const defaultTitle = `${data.admin__core_plugins__show.edges[0].name} - ${tCore('nav.plugins')} - ${t('title_short')} - ${config.settings.general.site_name}`; + const defaultTitle = `${data.admin__core_plugins__show.edges[0].name} - ${tCore('nav.plugins')} - ${t('title_short')} - ${config.core_settings__show.site_name}`; return { title: { diff --git a/packages/frontend/src/views/admin/views/core/styles/editor/content.tsx b/packages/frontend/src/views/admin/views/core/styles/editor/content.tsx index 5a5b7712d..ec7e92b67 100644 --- a/packages/frontend/src/views/admin/views/core/styles/editor/content.tsx +++ b/packages/frontend/src/views/admin/views/core/styles/editor/content.tsx @@ -1,7 +1,6 @@ 'use client'; import { useTranslations } from 'next-intl'; -import { ConfigType } from 'vitnode-shared'; import { useEditorAdmin } from './hooks/use-editor-admin'; import { FilesSectionContentEditorAdmin } from './sections/files'; @@ -15,8 +14,11 @@ import { } from '../../../../../../components/ui/form'; import { Switch } from '../../../../../../components/ui/switch'; import { Button } from '../../../../../../components/ui/button'; +import { Core_GlobalQuery } from '../../../../../../graphql/graphql'; -export const ContentEditorAdmin = (data: ConfigType) => { +export const ContentEditorAdmin = ( + data: Core_GlobalQuery['core_middleware__show']['editor'], +) => { const t = useTranslations('admin.core.styles.editor'); const tCore = useTranslations('core'); const { form, onSubmit } = useEditorAdmin(data); diff --git a/packages/frontend/src/views/admin/views/core/styles/editor/editor-admin-view.tsx b/packages/frontend/src/views/admin/views/core/styles/editor/editor-admin-view.tsx index 057b47256..c4853fd41 100644 --- a/packages/frontend/src/views/admin/views/core/styles/editor/editor-admin-view.tsx +++ b/packages/frontend/src/views/admin/views/core/styles/editor/editor-admin-view.tsx @@ -2,19 +2,19 @@ import { getTranslations } from 'next-intl/server'; import { ContentEditorAdmin } from './content'; -import { getConfigFile } from '../../../../../../helpers/config'; import { HeaderContent } from '../../../../../../components/ui/header-content'; +import { getGlobalData } from '../../../../../../graphql/get-global-data'; export const EditorAdminView = async () => { - const [data, t] = await Promise.all([ - getConfigFile(), + const [t, data] = await Promise.all([ getTranslations('admin.core.styles.editor'), + getGlobalData(), ]); return ( <> - + ); }; diff --git a/packages/frontend/src/views/admin/views/core/styles/editor/hooks/mutation-api.ts b/packages/frontend/src/views/admin/views/core/styles/editor/hooks/mutation-api.ts index 9b1d0d2d0..afdbf700d 100644 --- a/packages/frontend/src/views/admin/views/core/styles/editor/hooks/mutation-api.ts +++ b/packages/frontend/src/views/admin/views/core/styles/editor/hooks/mutation-api.ts @@ -1,17 +1,30 @@ 'use server'; -import * as fs from 'fs'; +import { revalidatePath } from 'next/cache'; -import { ConfigType } from 'vitnode-shared'; +import { fetcher } from '../../../../../../../graphql/fetcher'; +import { + Admin__Core_Styles__Editor__Edit, + Admin__Core_Styles__Editor__EditMutation, + Admin__Core_Styles__Editor__EditMutationVariables, +} from '../../../../../../../graphql/graphql'; -import { configPath, getConfigFile } from '../../../../../../../helpers/config'; +export const mutationApi = async ( + variables: Admin__Core_Styles__Editor__EditMutationVariables, +) => { + try { + const { data } = await fetcher< + Admin__Core_Styles__Editor__EditMutation, + Admin__Core_Styles__Editor__EditMutationVariables + >({ + query: Admin__Core_Styles__Editor__Edit, + variables, + }); -export const mutationApi = async (variables: ConfigType['editor']) => { - const config = await getConfigFile(); - const newData: ConfigType = { - ...config, - editor: variables, - }; + revalidatePath('/', 'layout'); - fs.writeFileSync(configPath, JSON.stringify(newData, null, 2), 'utf8'); + return { data }; + } catch (error) { + return { error }; + } }; diff --git a/packages/frontend/src/views/admin/views/core/styles/editor/hooks/use-editor-admin.ts b/packages/frontend/src/views/admin/views/core/styles/editor/hooks/use-editor-admin.ts index 663266cff..85a7ebdeb 100644 --- a/packages/frontend/src/views/admin/views/core/styles/editor/hooks/use-editor-admin.ts +++ b/packages/frontend/src/views/admin/views/core/styles/editor/hooks/use-editor-admin.ts @@ -3,24 +3,30 @@ import { useForm } from 'react-hook-form'; import * as z from 'zod'; import { toast } from 'sonner'; import { useTranslations } from 'next-intl'; -import { ConfigType } from 'vitnode-shared'; import { mutationApi } from './mutation-api'; -export const useEditorAdmin = (data: ConfigType) => { +import { + AllowTypeFilesEnum, + Core_GlobalQuery, +} from '../../../../../../../graphql/graphql'; + +export const useEditorAdmin = ( + data: Core_GlobalQuery['core_middleware__show']['editor'], +) => { const t = useTranslations('core'); const formSchema = z.object({ sticky: z.boolean(), files: z.object({ - allow_type: z.enum(['all', 'images_videos', 'images', 'none']), + allow_type: z.nativeEnum(AllowTypeFilesEnum), }), }); const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: { - sticky: data.editor.sticky, - files: data.editor.files, + sticky: data.sticky, + files: data.files, }, }); diff --git a/packages/frontend/src/views/admin/views/core/styles/nav/create-edit/hooks/create-mutation-api.ts b/packages/frontend/src/views/admin/views/core/styles/nav/create-edit/hooks/create-mutation-api.ts index 6c64c2b84..57ed35691 100644 --- a/packages/frontend/src/views/admin/views/core/styles/nav/create-edit/hooks/create-mutation-api.ts +++ b/packages/frontend/src/views/admin/views/core/styles/nav/create-edit/hooks/create-mutation-api.ts @@ -3,21 +3,21 @@ import { revalidatePath } from 'next/cache'; import { - Admin__Core_Nav__Create, - Admin__Core_Nav__CreateMutation, - Admin__Core_Nav__CreateMutationVariables, + Admin__Core_Styles__Nav__Create, + Admin__Core_Styles__Nav__CreateMutation, + Admin__Core_Styles__Nav__CreateMutationVariables, } from '../../../../../../../../graphql/graphql'; import { fetcher } from '../../../../../../../../graphql/fetcher'; export const createMutationApi = async ( - variables: Admin__Core_Nav__CreateMutationVariables, + variables: Admin__Core_Styles__Nav__CreateMutationVariables, ) => { try { const { data } = await fetcher< - Admin__Core_Nav__CreateMutation, - Admin__Core_Nav__CreateMutationVariables + Admin__Core_Styles__Nav__CreateMutation, + Admin__Core_Styles__Nav__CreateMutationVariables >({ - query: Admin__Core_Nav__Create, + query: Admin__Core_Styles__Nav__Create, variables, }); diff --git a/packages/frontend/src/views/admin/views/core/styles/nav/create-edit/hooks/edit-mutation-api.ts b/packages/frontend/src/views/admin/views/core/styles/nav/create-edit/hooks/edit-mutation-api.ts index 03929e4d1..fbaf1a963 100644 --- a/packages/frontend/src/views/admin/views/core/styles/nav/create-edit/hooks/edit-mutation-api.ts +++ b/packages/frontend/src/views/admin/views/core/styles/nav/create-edit/hooks/edit-mutation-api.ts @@ -4,20 +4,20 @@ import { revalidatePath } from 'next/cache'; import { fetcher } from '../../../../../../../../graphql/fetcher'; import { - Admin__Core_Nav__Edit, - Admin__Core_Nav__EditMutation, - Admin__Core_Nav__EditMutationVariables, + Admin__Core_Styles__Nav__Edit, + Admin__Core_Styles__Nav__EditMutation, + Admin__Core_Styles__Nav__EditMutationVariables, } from '../../../../../../../../graphql/graphql'; export const editMutationApi = async ( - variables: Admin__Core_Nav__EditMutationVariables, + variables: Admin__Core_Styles__Nav__EditMutationVariables, ) => { try { const { data } = await fetcher< - Admin__Core_Nav__EditMutation, - Admin__Core_Nav__EditMutationVariables + Admin__Core_Styles__Nav__EditMutation, + Admin__Core_Styles__Nav__EditMutationVariables >({ - query: Admin__Core_Nav__Edit, + query: Admin__Core_Styles__Nav__Edit, variables, }); diff --git a/packages/frontend/src/views/admin/views/core/styles/nav/table/actions/delete/hooks/mutation-api.ts b/packages/frontend/src/views/admin/views/core/styles/nav/table/actions/delete/hooks/mutation-api.ts index 8397f1d26..7f0eeed2d 100644 --- a/packages/frontend/src/views/admin/views/core/styles/nav/table/actions/delete/hooks/mutation-api.ts +++ b/packages/frontend/src/views/admin/views/core/styles/nav/table/actions/delete/hooks/mutation-api.ts @@ -4,20 +4,20 @@ import { revalidatePath } from 'next/cache'; import { fetcher } from '../../../../../../../../../../graphql/fetcher'; import { - Admin__Core_Nav__Delete, - Admin__Core_Nav__DeleteMutation, - Admin__Core_Nav__DeleteMutationVariables, + Admin__Core_Styles__Nav__Delete, + Admin__Core_Styles__Nav__DeleteMutation, + Admin__Core_Styles__Nav__DeleteMutationVariables, } from '../../../../../../../../../../graphql/graphql'; export const mutationApi = async ( - variables: Admin__Core_Nav__DeleteMutationVariables, + variables: Admin__Core_Styles__Nav__DeleteMutationVariables, ) => { try { const { data } = await fetcher< - Admin__Core_Nav__DeleteMutation, - Admin__Core_Nav__DeleteMutationVariables + Admin__Core_Styles__Nav__DeleteMutation, + Admin__Core_Styles__Nav__DeleteMutationVariables >({ - query: Admin__Core_Nav__Delete, + query: Admin__Core_Styles__Nav__Delete, variables, }); diff --git a/packages/frontend/src/views/admin/views/core/styles/nav/table/hooks/mutation-change-position-api.ts b/packages/frontend/src/views/admin/views/core/styles/nav/table/hooks/mutation-change-position-api.ts index 651e9bb26..973e35094 100644 --- a/packages/frontend/src/views/admin/views/core/styles/nav/table/hooks/mutation-change-position-api.ts +++ b/packages/frontend/src/views/admin/views/core/styles/nav/table/hooks/mutation-change-position-api.ts @@ -4,20 +4,20 @@ import { revalidatePath } from 'next/cache'; import { fetcher } from '../../../../../../../../graphql/fetcher'; import { - Admin__Core_Nav__Change_Position, - Admin__Core_Nav__Change_PositionMutation, - Admin__Core_Nav__Change_PositionMutationVariables, + Admin__Core_Nav_Styles__Change_Position, + Admin__Core_Nav_Styles__Change_PositionMutation, + Admin__Core_Nav_Styles__Change_PositionMutationVariables, } from '../../../../../../../../graphql/graphql'; export const mutationChangePositionApi = async ( - variables: Admin__Core_Nav__Change_PositionMutationVariables, + variables: Admin__Core_Nav_Styles__Change_PositionMutationVariables, ) => { try { const { data } = await fetcher< - Admin__Core_Nav__Change_PositionMutation, - Admin__Core_Nav__Change_PositionMutationVariables + Admin__Core_Nav_Styles__Change_PositionMutation, + Admin__Core_Nav_Styles__Change_PositionMutationVariables >({ - query: Admin__Core_Nav__Change_Position, + query: Admin__Core_Nav_Styles__Change_Position, variables, }); diff --git a/packages/frontend/src/views/admin/views/theme_editor/theme-editor-view.tsx b/packages/frontend/src/views/admin/views/theme_editor/theme-editor-view.tsx index fd6fc3ff9..6470713b3 100644 --- a/packages/frontend/src/views/admin/views/theme_editor/theme-editor-view.tsx +++ b/packages/frontend/src/views/admin/views/theme_editor/theme-editor-view.tsx @@ -21,12 +21,9 @@ const getData = async () => { }; export const ThemeEditorView = async () => { - const [data, session] = await Promise.all([ - getData(), - await getSessionData(), - ]); + const [data, session] = await Promise.all([getData(), getSessionData()]); - if (!session.data.core_sessions__authorization.user?.is_admin) { + if (!session.core_sessions__authorization.user?.is_admin) { return ; } diff --git a/packages/frontend/src/views/layout/auth/auth-layout.tsx b/packages/frontend/src/views/layout/auth/auth-layout.tsx index 79ac15c5f..1a52e022d 100644 --- a/packages/frontend/src/views/layout/auth/auth-layout.tsx +++ b/packages/frontend/src/views/layout/auth/auth-layout.tsx @@ -13,7 +13,7 @@ interface Props { export const AuthLayout = async ({ children }: Props) => { try { - const { data } = await getSessionData(); + const data = await getSessionData(); // TODO: Improve this check, make this based on the users count if (data.core_languages__show.edges.length === 0) { redirect('/admin/install'); diff --git a/packages/frontend/src/views/layout/providers.tsx b/packages/frontend/src/views/layout/providers.tsx index e6cb7e947..dbdaac753 100644 --- a/packages/frontend/src/views/layout/providers.tsx +++ b/packages/frontend/src/views/layout/providers.tsx @@ -3,19 +3,17 @@ import * as React from 'react'; import { ThemeProvider as NextThemesProvider } from 'next-themes'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { ConfigType } from 'vitnode-shared'; import { GlobalsContext } from '../../hooks/use-globals'; import { Toaster } from '../../components/ui/sonner'; -import { Core_MiddlewareQuery } from '../../graphql/graphql'; +import { Core_GlobalQuery } from '../../graphql/graphql'; interface Props { children: React.ReactNode; - config: ConfigType; - middlewareData?: Core_MiddlewareQuery; + middlewareData?: Core_GlobalQuery; } -export const RootProviders = ({ children, middlewareData, config }: Props) => { +export const RootProviders = ({ children, middlewareData }: Props) => { const [queryClient] = React.useState( () => new QueryClient({ @@ -40,7 +38,15 @@ export const RootProviders = ({ children, middlewareData, config }: Props) => { middlewareData?.core_languages__show.edges.find( lang => lang.default, )?.code ?? 'en', - config, + settings: middlewareData?.core_settings__show ?? { + site_copyright: [], + site_description: [], + site_name: '', + site_short_name: '', + }, + config: + middlewareData?.core_middleware__show ?? + ({} as Core_GlobalQuery['core_middleware__show']), }} > => { - const config = await getConfigFile(); - const defaultTitle = config.settings.general.site_name; - const metadata: Metadata = { manifest: `${CONFIG.backend_public_url}/assets/${locale}/manifest.webmanifest`, - title: { - default: defaultTitle, - template: `%s - ${defaultTitle}`, - }, icons: { icon: '/icons/favicon.ico', }, }; try { - await getMiddlewareData(); + const { + core_settings__show: { site_name }, + } = await getGlobalData(); - return metadata; + return { + ...metadata, + title: { + default: site_name, + template: `%s - ${site_name}`, + }, + }; } catch (e) { return { ...metadata, - title: `Error 500 - ${defaultTitle}`, + title: 'Error 500!', robots: 'noindex, nofollow', }; } }; -const getMiddlewareData = async () => { - const { data } = await fetcher({ - query: Core_Middleware, - cache: 'force-cache', - }); - - return data; -}; - export const RootLayout = async ({ children, params: { locale }, className, }: RootLayoutProps) => { - const [messages, config] = await Promise.all([ - getMessages(), - getConfigFile(), - ]); + const messages = await getMessages(); try { - const middlewareData = await getMiddlewareData(); + const middlewareData = await getGlobalData(); return ( @@ -78,7 +65,7 @@ export const RootLayout = async ({ showSpinner={false} height={4} /> - + {children} @@ -90,7 +77,7 @@ export const RootLayout = async ({ return ( - + diff --git a/packages/frontend/src/views/theme/layout/footer.tsx b/packages/frontend/src/views/theme/layout/footer.tsx index b00dce1ce..d12a5ab4b 100644 --- a/packages/frontend/src/views/theme/layout/footer.tsx +++ b/packages/frontend/src/views/theme/layout/footer.tsx @@ -9,9 +9,7 @@ interface Props { export const Footer = async ({ locale }: Props) => { const { convertText } = getTextLang({ locale }); const { - data: { - core_settings__show: { site_copyright }, - }, + core_settings__show: { site_copyright }, } = await getSessionData(); return ( diff --git a/packages/frontend/src/views/theme/layout/header/header.tsx b/packages/frontend/src/views/theme/layout/header/header.tsx index 15a0ff204..97e8ee2e9 100644 --- a/packages/frontend/src/views/theme/layout/header/header.tsx +++ b/packages/frontend/src/views/theme/layout/header/header.tsx @@ -11,9 +11,7 @@ import { getSessionData } from '../../../../graphql/get-session-data'; export const Header = async () => { const { - data: { - core_sessions__authorization: { user }, - }, + core_sessions__authorization: { user }, } = await getSessionData(); return ( diff --git a/packages/frontend/src/views/theme/layout/nav/nav.tsx b/packages/frontend/src/views/theme/layout/nav/nav.tsx index 660896081..7c51ffb8a 100644 --- a/packages/frontend/src/views/theme/layout/nav/nav.tsx +++ b/packages/frontend/src/views/theme/layout/nav/nav.tsx @@ -8,7 +8,7 @@ import { Icon } from '../../../../components/icon/icon'; import { ShowCoreNav } from '../../../../graphql/graphql'; export const Nav = async () => { - const { data } = await getSessionData(); + const data = await getSessionData(); const flattenData = flattenTree({ tree: data.core_nav__show.edges.map(nav => ({ diff --git a/packages/frontend/src/views/theme/layout/quick-menu/quick-menu.tsx b/packages/frontend/src/views/theme/layout/quick-menu/quick-menu.tsx index 6f1b42f14..7d683d4a9 100644 --- a/packages/frontend/src/views/theme/layout/quick-menu/quick-menu.tsx +++ b/packages/frontend/src/views/theme/layout/quick-menu/quick-menu.tsx @@ -7,7 +7,7 @@ import { getSessionData } from '../../../../graphql/get-session-data'; import { Icon } from '../../../../components/icon/icon'; export const QuickMenu = async () => { - const { data } = await getSessionData(); + const data = await getSessionData(); const flattenData = flattenTree({ tree: data.core_nav__show.edges.map(nav => ({ diff --git a/packages/frontend/tsup.config.ts b/packages/frontend/tsup.config.ts deleted file mode 100644 index f42bda62f..000000000 --- a/packages/frontend/tsup.config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from 'tsup'; - -export default defineConfig({ - entry: ['scripts/setup.ts'], - outDir: 'dist/scripts', - clean: false, - minify: true, -}); diff --git a/packages/shared/src/config.type.ts b/packages/shared/src/config.type.ts deleted file mode 100644 index b00126b3d..000000000 --- a/packages/shared/src/config.type.ts +++ /dev/null @@ -1,27 +0,0 @@ -export interface ConfigType { - editor: { - files: { - allow_type: 'all' | 'images_videos' | 'images' | 'none'; - }; - sticky: boolean; - }; - langs: { - code: string; - default: boolean; - enabled: boolean; - }[]; - rebuild_required: { - langs: boolean; - plugins: boolean; - }; - settings: { - email: { - color_primary: string; - color_primary_foreground: string; - }; - general: { - site_name: string; - site_short_name: string; - }; - }; -} diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index f611b2f38..a6bd9cdc1 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -3,4 +3,3 @@ export * from './generate-random-string'; export * from './remove-special-characters'; export * from './colors'; export * from './format-file-size'; -export * from './config.type'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7829746b9..b83a10869 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -750,16 +750,16 @@ importers: version: 0.399.0(react@19.0.0-rc.0) next: specifier: 15.0.0-canary.46 - version: 15.0.0-canary.46(babel-plugin-react-compiler@0.0.0-experimental-696af53-20240625)(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0) + version: 15.0.0-canary.46(@babel/core@7.24.7)(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0) next-intl: specifier: ^3.15.3 - version: 3.15.3(next@15.0.0-canary.46(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0))(react@19.0.0-rc.0) + version: 3.15.3(next@15.0.0-canary.46(@babel/core@7.24.7)(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0))(react@19.0.0-rc.0) next-themes: specifier: ^0.3.0 version: 0.3.0(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0) nextjs-toploader: specifier: ^1.6.12 - version: 1.6.12(next@15.0.0-canary.46(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0))(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0) + version: 1.6.12(next@15.0.0-canary.46(@babel/core@7.24.7)(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0))(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0) nprogress: specifier: ^0.2.0 version: 0.2.0 @@ -860,9 +860,6 @@ importers: ts-node: specifier: ^10.9.2 version: 10.9.2(@swc/core@1.6.5)(@types/node@20.14.9)(typescript@5.5.2) - tsup: - specifier: ^8.1.0 - version: 8.1.0(@swc/core@1.6.5)(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.6.5)(@types/node@20.14.9)(typescript@5.5.2))(typescript@5.5.2) typescript: specifier: ^5.5.2 version: 5.5.2 @@ -13735,6 +13732,23 @@ snapshots: '@swc/core-win32-x64-msvc': 1.3.101 '@swc/helpers': 0.5.11 + '@swc/core@1.6.5': + dependencies: + '@swc/counter': 0.1.3 + '@swc/types': 0.1.9 + optionalDependencies: + '@swc/core-darwin-arm64': 1.6.5 + '@swc/core-darwin-x64': 1.6.5 + '@swc/core-linux-arm-gnueabihf': 1.6.5 + '@swc/core-linux-arm64-gnu': 1.6.5 + '@swc/core-linux-arm64-musl': 1.6.5 + '@swc/core-linux-x64-gnu': 1.6.5 + '@swc/core-linux-x64-musl': 1.6.5 + '@swc/core-win32-arm64-msvc': 1.6.5 + '@swc/core-win32-ia32-msvc': 1.6.5 + '@swc/core-win32-x64-msvc': 1.6.5 + optional: true + '@swc/core@1.6.5(@swc/helpers@0.5.11)': dependencies: '@swc/counter': 0.1.3 @@ -18362,6 +18376,14 @@ snapshots: neo-async@2.6.2: {} + next-intl@3.15.3(next@15.0.0-canary.46(@babel/core@7.24.7)(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0))(react@19.0.0-rc.0): + dependencies: + '@formatjs/intl-localematcher': 0.2.32 + negotiator: 0.6.3 + next: 15.0.0-canary.46(@babel/core@7.24.7)(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0) + react: 19.0.0-rc.0 + use-intl: 3.15.3(react@19.0.0-rc.0) + next-intl@3.15.3(next@15.0.0-canary.46(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0))(react@19.0.0-rc.0): dependencies: '@formatjs/intl-localematcher': 0.2.32 @@ -18448,6 +18470,32 @@ snapshots: - '@babel/core' - babel-plugin-macros + next@15.0.0-canary.46(@babel/core@7.24.7)(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0): + dependencies: + '@next/env': 15.0.0-canary.46 + '@swc/helpers': 0.5.11 + busboy: 1.6.0 + caniuse-lite: 1.0.30001636 + graceful-fs: 4.2.11 + postcss: 8.4.31 + react: 19.0.0-rc.0 + react-dom: 19.0.0-rc.0(react@19.0.0-rc.0) + styled-jsx: 5.1.6(@babel/core@7.24.7)(react@19.0.0-rc.0) + optionalDependencies: + '@next/swc-darwin-arm64': 15.0.0-canary.46 + '@next/swc-darwin-x64': 15.0.0-canary.46 + '@next/swc-linux-arm64-gnu': 15.0.0-canary.46 + '@next/swc-linux-arm64-musl': 15.0.0-canary.46 + '@next/swc-linux-x64-gnu': 15.0.0-canary.46 + '@next/swc-linux-x64-musl': 15.0.0-canary.46 + '@next/swc-win32-arm64-msvc': 15.0.0-canary.46 + '@next/swc-win32-ia32-msvc': 15.0.0-canary.46 + '@next/swc-win32-x64-msvc': 15.0.0-canary.46 + sharp: 0.33.4 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + next@15.0.0-canary.46(babel-plugin-react-compiler@0.0.0-experimental-696af53-20240625)(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0): dependencies: '@next/env': 15.0.0-canary.46 @@ -18475,9 +18523,9 @@ snapshots: - '@babel/core' - babel-plugin-macros - nextjs-toploader@1.6.12(next@15.0.0-canary.46(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0))(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0): + nextjs-toploader@1.6.12(next@15.0.0-canary.46(@babel/core@7.24.7)(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0))(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0): dependencies: - next: 15.0.0-canary.46(babel-plugin-react-compiler@0.0.0-experimental-696af53-20240625)(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0) + next: 15.0.0-canary.46(@babel/core@7.24.7)(react-dom@19.0.0-rc.0(react@19.0.0-rc.0))(react@19.0.0-rc.0) nprogress: 0.2.0 prop-types: 15.8.1 react: 19.0.0-rc.0 @@ -20098,6 +20146,13 @@ snapshots: optionalDependencies: '@babel/core': 7.24.5 + styled-jsx@5.1.6(@babel/core@7.24.7)(react@19.0.0-rc.0): + dependencies: + client-only: 0.0.1 + react: 19.0.0-rc.0 + optionalDependencies: + '@babel/core': 7.24.7 + styled-jsx@5.1.6(react@19.0.0-rc.0): dependencies: client-only: 0.0.1 @@ -20406,7 +20461,7 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 optionalDependencies: - '@swc/core': 1.6.5(@swc/helpers@0.5.11) + '@swc/core': 1.6.5 ts-node@10.9.2(@types/node@20.14.8)(typescript@5.5.2): dependencies: