Skip to content

Commit

Permalink
Merge pull request #637 from VitNode/perf/delete_default_plugin
Browse files Browse the repository at this point in the history
perf: Delete default plugin column from database
  • Loading branch information
aXenDeveloper authored Jan 6, 2025
2 parents ecd5886 + 22551d3 commit 36a94f8
Show file tree
Hide file tree
Showing 24 changed files with 95 additions and 291 deletions.
5 changes: 2 additions & 3 deletions apps/backend/src/plugins/welcome/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,5 @@
"code": "welcome",
"author": "VitNode",
"author_url": "https://vitnode.com/",
"support_url": "https://github.com/VitNode/vitnode/issues",
"allow_default": true
}
"support_url": "https://github.com/VitNode/vitnode/issues"
}
18 changes: 3 additions & 15 deletions apps/frontend/src/app/[locale]/(main)/(layout)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,9 @@
// ! DO NOT TOUCH THIS FILE!!!
// ! If you remove this then default page plugin will not work
import DefaultPage from '@/plugins/welcome/templates/default-page';
import React from 'react';
import { getMiddlewareData } from 'vitnode-frontend/api/get-middleware-data';
import { generateMetadataDefaultPage } from 'vitnode-frontend/views/theme/views/default-page';

export const generateMetadata = generateMetadataDefaultPage;

export default async function Page() {
const { plugin_code_default } = await getMiddlewareData();

const PageFromTheme = React.lazy(async () =>
import(`@/plugins/${plugin_code_default}/templates/default-page`).then(
module => ({
default: module.default,
}),
),
);

return <PageFromTheme />;
export default function Page() {
return <DefaultPage />;
}
12 changes: 0 additions & 12 deletions docs/dev/i18n/namespaces.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,3 @@ Provide the list of namespaces that you want to get access to the translation st
You don't need to include the `core.global` namespace in the `namespaces`
prop. It's already included by default.
</Callout>

### Default page

VitNode has plugin system with option to set plugin as default. That means default plugin will be loaded on the home page.

To set default page make sure your have `default-page.tsx` inside `templates` folder plugin with `export default` function.

```tsx title="apps/frontend/src/plugins/{your_plugin}/templates/default-page.tsx"
export default function Page() {
return <div>Hello World</div>;
}
```
1 change: 0 additions & 1 deletion docs/dev/permissions-admin.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ Edit the `permissions_admin` in the `config.json` file from your plugin.
"author": "VitNode",
"author_url": "https://vitnode.com/",
"support_url": "https://github.com/VitNode/vitnode/issues",
"allow_default": true,
// [!code ++]
"permissions_admin": [
// [!code ++]
Expand Down
95 changes: 43 additions & 52 deletions packages/backend/scripts/update-plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ export const updatePlugins = async ({
db: NodePgDatabase<typeof coreSchemaDatabase>;
pluginsPath: string;
}) => {
let isDefaultIndex: null | number = null;
const defaultPlugin = await db.query.core_plugins.findFirst({
where: (table, { eq }) => eq(table.default, true),
});
const plugins = (await readdir(pluginsPath)).filter(
plugin => !['core', 'plugins.module.ts'].includes(plugin),
);
Expand All @@ -30,58 +26,53 @@ export const updatePlugins = async ({
},
});

for (const [index, code] of plugins.entries()) {
const pluginPath = join(pluginsPath, code);
const configPath = join(pluginPath, 'config.json');
if (!existsSync(configPath)) {
continue;
}

const config = JSON.parse(
await readFile(join(pluginPath, 'config.json'), 'utf8'),
);
await Promise.all(
plugins.map(async code => {
const pluginPath = join(pluginsPath, code);
const configPath = join(pluginPath, 'config.json');
if (!existsSync(configPath)) {
return;
}

if (config.allow_default && isDefaultIndex === null) {
isDefaultIndex = index;
}
const config = JSON.parse(
await readFile(join(pluginPath, 'config.json'), 'utf8'),
);

const plugin = pluginsFromDatabase.find(
plugin => plugin.code === config.code,
);
const plugin = pluginsFromDatabase.find(
plugin => plugin.code === config.code,
);

if (plugin) {
await tx
.update(core_plugins)
.set({
name: config.name,
description: config.description,
support_url: config.support_url,
author: config.author,
author_url: config.author_url,
allow_default: config.allow_default,
version: config.version,
version_code: config.version_code,
})
.where(eq(core_plugins.id, plugin.id));
} else {
await tx.insert(core_plugins).values([
{
name: config.name,
description: config.description,
code: config.code,
support_url: config.support_url,
author: config.author,
author_url: config.author_url,
allow_default: config.allow_default,
version: config.version,
version_code: config.version_code,
default: isDefaultIndex === index && !defaultPlugin,
},
]);
}
if (plugin) {
await tx
.update(core_plugins)
.set({
name: config.name,
description: config.description,
support_url: config.support_url,
author: config.author,
author_url: config.author_url,
version: config.version,
version_code: config.version_code,
})
.where(eq(core_plugins.id, plugin.id));
} else {
await tx.insert(core_plugins).values([
{
name: config.name,
description: config.description,
code: config.code,
support_url: config.support_url,
author: config.author,
author_url: config.author_url,
version: config.version,
version_code: config.version_code,
},
]);
}

await tx.execute(sql`commit`);
}
await tx.execute(sql`commit`);
}),
);

// Remove plugins that are not in the plugins folder
const pluginsToDelete = pluginsFromDatabase.filter(
Expand Down
7 changes: 0 additions & 7 deletions packages/backend/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,6 @@ export const ABSOLUTE_PATHS = {
plugin: join(internalPaths.frontend, 'plugins', code),
templates: join(internalPaths.frontend, 'plugins', code, 'templates'),
languages: join(internalPaths.frontend, 'plugins', code, 'langs'),
default_page: join(
internalPaths.frontend,
'plugins',
code,
'templates',
'default-page.tsx',
),
admin_pages_auth: join(
internalPaths.frontend,
'app',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ export class CreatePluginsAdminService {
$schema: 'https://api.vitnode.com/public/vitnode/plugin.schema.json',
code,
...rest,
allow_default: true,
nav: [],
version: '0.0.1',
version_code: 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
Injectable,
NotFoundException,
} from '@nestjs/common';
import { eq } from 'drizzle-orm';
import { count, eq } from 'drizzle-orm';
import { existsSync } from 'fs';
import { rm } from 'fs/promises';
import { join } from 'path';
Expand All @@ -35,16 +35,21 @@ export class DeletePluginsAdminService {
where: (table, { eq }) => eq(table.id, id),
columns: {
code: true,
default: true,
},
});

if (!plugin) {
throw new NotFoundException();
}

if (plugin.default) {
throw new BadRequestException('DEFAULT_PLUGIN_CANNOT_BE_DELETED');
const [pluginCount] = await this.databaseService.db
.select({
count: count(),
})
.from(core_plugins);

if (pluginCount.count === 1) {
throw new BadRequestException('Cannot delete the last plugin');
}

await this.changeFilesHelper.changeFiles({
Expand Down
33 changes: 8 additions & 25 deletions packages/backend/src/core/admin/plugins/services/edit.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
Injectable,
NotFoundException,
} from '@nestjs/common';
import { eq, ne } from 'drizzle-orm';
import { eq } from 'drizzle-orm';
import { readFile, writeFile } from 'fs/promises';
import {
ConfigPlugin,
Expand All @@ -20,7 +20,7 @@ export class EditPluginsAdminService {

async edit({
code,
body: { default: isDefault = false, ...rest },
body,
}: {
body: EditPluginsAdminBody;
code: string;
Expand All @@ -37,26 +37,9 @@ export class EditPluginsAdminService {
throw new BadRequestException('PLUGIN_CODE_MISMATCH');
}

if (isDefault) {
if (!plugin.enabled) {
throw new BadRequestException('PLUGIN_NOT_ENABLED');
}

// Set all other plugins to default: false
await this.databaseService.db
.update(core_plugins)
.set({
default: false,
})
.where(ne(core_plugins.code, code));
}

const [updatePlugin] = await this.databaseService.db
.update(core_plugins)
.set({
...rest,
default: isDefault,
})
.set(body)
.where(eq(core_plugins.code, code))
.returning();

Expand All @@ -66,11 +49,11 @@ export class EditPluginsAdminService {
await readFile(path, 'utf8'),
);

config.name = rest.name;
config.description = rest.description;
config.author = rest.author;
config.author_url = rest.author_url;
config.support_url = rest.support_url;
config.name = body.name;
config.description = body.description;
config.author = body.author;
config.author_url = body.author_url;
config.support_url = body.support_url;

await writeFile(path, JSON.stringify(config, null, 2));

Expand Down
32 changes: 8 additions & 24 deletions packages/backend/src/core/admin/plugins/services/export.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ export class ExportPluginsAdminService {
const configJSON: ConfigPlugin = JSON.parse(
await readFile(pathInfoJSON, 'utf8'),
);
const allow_default = existsSync(
ABSOLUTE_PATHS.plugin({ code }).frontend.default_page,
);

if (
(!version && !configJSON.version) ||
Expand All @@ -66,32 +63,19 @@ export class ExportPluginsAdminService {
});
}

configJSON.allow_default = allow_default;
configJSON.version = version ?? configJSON.version;
configJSON.version_code = version_code ?? configJSON.version_code;

await writeFile(pathInfoJSON, JSON.stringify(configJSON, null, 2), 'utf8');

// Update only allow_default
if (!version || !version_code) {
await this.databaseService.db
.update(core_plugins)
.set({
allow_default,
updated_at: new Date(),
})
.where(eq(core_plugins.code, code));
} else {
await this.databaseService.db
.update(core_plugins)
.set({
version,
version_code,
allow_default,
updated_at: new Date(),
})
.where(eq(core_plugins.code, code));
}
await this.databaseService.db
.update(core_plugins)
.set({
version,
version_code,
updated_at: new Date(),
})
.where(eq(core_plugins.code, code));

// Prepare the export
const tempFolderName = removeSpecialCharacters(
Expand Down
6 changes: 0 additions & 6 deletions packages/backend/src/core/middleware/services/show.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ export class ShowMiddlewareService {
this.databaseService.db.query.core_plugins.findMany({
columns: {
code: true,
default: true,
},
}),
this.databaseService.db.query.core_languages.findMany({
Expand All @@ -76,10 +75,6 @@ export class ShowMiddlewareService {
}),
]);

const plugin_code_default = plugins.find(plugin => plugin.default)?.code;
if (!plugin_code_default) {
throw new InternalServerErrorException('Plugin not found');
}
const manifest = await this.getManifests({
langCodes: langs.map(lang => lang.code),
});
Expand Down Expand Up @@ -124,7 +119,6 @@ export class ShowMiddlewareService {
editor: {
sticky: configFromDb.editor_sticky ?? false,
},
plugin_code_default,
site_description: manifest.map(item => ({
language_code: item.lang,
value: item.description,
Expand Down
2 changes: 0 additions & 2 deletions packages/backend/src/database/schema/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ export const core_plugins = pgTable(
support_url: t.varchar({ length: 255 }).notNull(),
author: t.varchar({ length: 100 }).notNull(),
author_url: t.varchar({ length: 255 }),
default: t.boolean().notNull().default(false),
allow_default: t.boolean().notNull().default(true),
}),
t => [
index('core_plugins_code_idx').on(t.code),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"$schema": "https://api.vitnode.com/public/vitnode/plugin.schema.json",
"name": "Welcome",
"description": "Basic plugin with default page.",
"version": "1.0.0",
Expand All @@ -7,6 +8,5 @@
"author": "VitNode",
"author_url": "https://vitnode.com/",
"support_url": "https://github.com/VitNode/vitnode/issues",
"allow_default": true,
"nav": []
}
}
Loading

0 comments on commit 36a94f8

Please sign in to comment.