Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add import plugin #613

Merged
merged 4 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions apps/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,17 @@
"db": "vitnode-backend db"
},
"dependencies": {
"@nestjs/cache-manager": "^3.0.0-next.0",
"@nestjs/cache-manager": "3.0.0-next.0",
"@nestjs/common": "^10.4.15",
"@nestjs/core": "^10.4.15",
"@nestjs/platform-express": "^10.4.15",
"@nestjs/schedule": "^4.1.2",
"@nestjs/swagger": "^8.1.0",
"@react-email/components": "^0.0.31",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"drizzle-kit": "^0.30.0",
"drizzle-orm": "^0.38.1",
"drizzle-kit": "^0.30.1",
"drizzle-orm": "^0.38.2",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"reflect-metadata": "^0.2.2",
Expand All @@ -38,7 +39,7 @@
"@swc/cli": "^0.5.2",
"@types/express": "^5.0.0",
"@types/node": "^22.10.2",
"@types/react": "^19.0.1",
"@types/react": "^19.0.2",
"cross-env": "^7.0.3",
"eslint-config-typescript-vitnode": "workspace:*",
"shared": "workspace:*",
Expand Down
11 changes: 5 additions & 6 deletions apps/backend/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// import { aiOpenAi } from 'vitnode-backend-ai-open-ai';
import { CacheModule } from '@nestjs/cache-manager';
import { Module } from '@nestjs/common';
import { emailResend } from 'vitnode-backend-email-resend';
// import { emailResend } from 'vitnode-backend-email-resend';
import { VitNodeCoreModule } from 'vitnode-backend/app.module';

import { DATABASE_ENVS, schemaDatabase } from './database/config';
Expand All @@ -17,11 +17,10 @@ import { PluginsModule } from './plugins/plugins.module';
config: DATABASE_ENVS,
schemaDatabase,
},
ssoLoginMethod: [],
email: emailResend({
api_key: process.env.EMAIL_RESEND_API_KEY,
from: process.env.EMAIL_RESEND_FROM,
}),
// email: emailResend({
// api_key: process.env.EMAIL_RESEND_API_KEY,
// from: process.env.EMAIL_RESEND_FROM,
// }),
// email: emailSMTP({
// host: process.env.EMAIL_SMTP_HOST,
// port: process.env.EMAIL_SMTP_PORT,
Expand Down
10 changes: 5 additions & 5 deletions apps/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
"@hookform/resolvers": "^3.9.1",
"geist": "^1.3.1",
"lucide-react": "^0.468.0",
"next": "^15.1.0",
"next-intl": "^3.26.1",
"next": "^15.1.2",
"next-intl": "^3.26.2",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-hook-form": "^7.54.1",
Expand All @@ -28,16 +28,16 @@
"zod": "^3.24.1"
},
"devDependencies": {
"@next/bundle-analyzer": "^15.1.0",
"@next/bundle-analyzer": "^15.1.2",
"@types/node": "^22.10.2",
"@types/react": "^19.0.1",
"@types/react": "^19.0.2",
"@types/react-dom": "^19.0.2",
"autoprefixer": "^10.4.20",
"cross-env": "^7.0.3",
"eslint-config-typescript-vitnode": "workspace:*",
"postcss": "^8.4.49",
"shared": "workspace:*",
"tailwindcss": "^3.4.16",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2",
"vitnode-shared": "workspace:*"
}
Expand Down
12 changes: 9 additions & 3 deletions apps/frontend/src/plugins/admin/langs/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -426,18 +426,24 @@
},
"upload": {
"title": "Upload Plugin",
"desc": "Upload a new plugin to your website.",
"title_new_version": "Upload New Version Plugin",
"info": "After uploading the plugin, you need to restart the server to apply the changes.",
"info": "After the process will be complete, you need to restart the server to apply the changes.",
"errors": {
"PLUGIN_ALREADY_EXISTS": "Plugin with this code already exists. If you want to update the plugin, use the upload new version form from the plugin dropdown menu.",
"PLUGIN_VERSION_IS_LOWER": "The version of the uploaded plugin is lower than the current version."
"PLUGIN_VERSION_IS_LOWER": "The version of the uploaded plugin is lower than the current version.",
"CONFLICT_PLUGIN_CODE": "Files with the same name already exist your project. Please remove them and try again."
},
"success": {
"upload": "Plugin has been uploaded.",
"new_version": "New version of the plugin has been uploaded."
},
"submit": "Upload"
},
"delete": {
"submit": "Yes, delete plugin",
"desc": "This action will delete <name></name> plugin created by <author></author> and all data associated with it.",
"info": "After the process is complete, you need to restart the server to apply the changes."
"info": "After the process will be complete, you need to restart the server to apply the changes."
}
},
"styles": {
Expand Down
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
"apps/*",
"packages/*"
],
"pnpm": {
"overrides": {
"esbuild": "0.24.0"
}
},
"devDependencies": {
"@types/node": "^22.10.2",
"eslint-config-typescript-vitnode": "workspace:*",
Expand Down
13 changes: 8 additions & 5 deletions packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"express"
],
"peerDependencies": {
"@nestjs/cache-manager": "3.0.0-next.0",
"@nestjs/common": "^10.4.15",
"@nestjs/core": "^10.4.15",
"@nestjs/platform-express": "^10.4.15",
Expand All @@ -76,10 +77,12 @@
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"react": "^19.0.0",
"react-dom": "^19.0.0"
"react-dom": "^19.0.0",
"drizzle-kit": "^0.30.1",
"drizzle-orm": "^0.38.2"
},
"devDependencies": {
"@nestjs/cache-manager": "^3.0.0-next.0",
"@nestjs/cache-manager": "3.0.0-next.0",
"@nestjs/common": "^10.4.15",
"@nestjs/core": "^10.4.15",
"@nestjs/platform-express": "^10.4.15",
Expand All @@ -92,13 +95,13 @@
"@types/multer": "^1.4.12",
"@types/node": "^22.10.2",
"@types/pg": "^8.11.10",
"@types/react": "^19.0.1",
"@types/react": "^19.0.2",
"@types/ua-parser-js": "^0.7.39",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"concurrently": "^9.1.0",
"drizzle-kit": "^0.30.0",
"drizzle-orm": "^0.38.1",
"drizzle-kit": "^0.30.1",
"drizzle-orm": "^0.38.2",
"eslint-config-typescript-vitnode": "workspace:*",
"react": "^19.0.0",
"react-dom": "^19.0.0",
Expand Down
1 change: 0 additions & 1 deletion packages/backend/scripts/update-plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ export const updatePlugins = async ({
return;
}

// const config: ConfigPlugin = JSON.parse(
const config = JSON.parse(
await readFile(join(pluginPath, 'config.json'), 'utf8'),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export class ValidateFilesPluginsAdminHelpersService {
pluginPath.frontend.plugin,
// Shared
pluginPath.shared,
// Backend
pluginPath.root,
];

// Check if the folders exist
Expand Down
26 changes: 26 additions & 0 deletions packages/backend/src/core/admin/plugins/plugins.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type { Response } from 'express';

import { OnlyForDevelopment } from '@/guards/dev.guard';
import { Controllers } from '@/helpers/controller.decorator';
import { FilesValidationPipe } from '@/helpers/files/files.pipe';
import { UploadFilesMethod } from '@/helpers/upload-files.decorator';
import {
Body,
Delete,
Expand All @@ -11,6 +13,7 @@ import {
Put,
Query,
Res,
UploadedFiles,
UseGuards,
} from '@nestjs/common';
import { ApiCreatedResponse, ApiOkResponse } from '@nestjs/swagger';
Expand All @@ -21,6 +24,7 @@ import {
ShowPluginAdmin,
ShowPluginsAdminObj,
ShowPluginsAdminQuery,
UploadPluginsAdminBody,
} from 'vitnode-shared/admin/plugins.dto';

import { CreatePluginsAdminService } from './services/create.service';
Expand All @@ -29,6 +33,7 @@ import { EditPluginsAdminService } from './services/edit.service';
import { ExportPluginsAdminService } from './services/export.service';
import { ItemPluginsAdminService } from './services/item.service';
import { ShowPluginsAdminService } from './services/show.service';
import { UploadPluginsAdminService } from './services/upload.service';

@Controllers({ plugin_name: 'Core', plugin_code: 'plugins', isAdmin: true })
export class PluginsAdminController {
Expand All @@ -39,6 +44,7 @@ export class PluginsAdminController {
private readonly itemService: ItemPluginsAdminService,
private readonly editService: EditPluginsAdminService,
private readonly exportService: ExportPluginsAdminService,
private readonly uploadService: UploadPluginsAdminService,
) {}

@ApiCreatedResponse({ description: 'Plugin created', type: ShowPluginAdmin })
Expand Down Expand Up @@ -93,4 +99,24 @@ export class PluginsAdminController {
): Promise<ShowPluginsAdminObj> {
return await this.showService.show(query);
}

@ApiCreatedResponse({ description: 'Plugin uploaded' })
@Post('upload')
@UploadFilesMethod({ fields: ['file'] })
@UseGuards(OnlyForDevelopment)
async uploadPlugin(
@UploadedFiles(
new FilesValidationPipe({
file: {
maxSize: 1024 * 1024 * 10, // 10 MB
acceptMimeType: ['application/gzip', 'application/x-compressed'],
maxCount: 1,
},
}),
)
files: Pick<UploadPluginsAdminBody, 'file'>,
@Body() body: UploadPluginsAdminBody,
): Promise<void> {
await this.uploadService.upload({ files, body });
}
}
2 changes: 2 additions & 0 deletions packages/backend/src/core/admin/plugins/plugins.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { EditPluginsAdminService } from './services/edit.service';
import { ExportPluginsAdminService } from './services/export.service';
import { ItemPluginsAdminService } from './services/item.service';
import { ShowPluginsAdminService } from './services/show.service';
import { UploadPluginsAdminService } from './services/upload.service';

@Module({
providers: [
Expand All @@ -22,6 +23,7 @@ import { ShowPluginsAdminService } from './services/show.service';
ItemPluginsAdminService,
EditPluginsAdminService,
ExportPluginsAdminService,
UploadPluginsAdminService,
],
controllers: [PluginsAdminController],
imports: [NavPluginsAdminModule, PermissionsAdminPluginsAdminModule],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import { eq } from 'drizzle-orm';
import { existsSync } from 'fs';
import { rm } from 'fs/promises';
import { join } from 'path';

import { ChangeFilesPluginsAdminHelpersService } from '../helpers/change-files.service';

Expand Down Expand Up @@ -71,6 +72,11 @@ export class DeletePluginsAdminService {
// Shared
await this.deleteFolderWhenExists(pluginPaths.shared);

// Uploads
await this.deleteFolderWhenExists(
join(ABSOLUTE_PATHS.uploads.public, plugin.code),
);

await Promise.all([
this.databaseService.db
.delete(core_plugins)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ export class ExportPluginsAdminService {
await cp(backendSource, backendPath, { recursive: true });

// Copy frontend files
const pathFiles = ABSOLUTE_PATHS.plugin({ code });
const frontendPaths = [
'admin_pages_auth',
'admin_pages',
Expand All @@ -127,7 +128,7 @@ export class ExportPluginsAdminService {
] as const;
await Promise.all(
frontendPaths.map(async path => {
const source = ABSOLUTE_PATHS.plugin({ code }).frontend[path];
const source = pathFiles.frontend[path];
if (!existsSync(source)) {
if (path === 'plugin') {
return res
Expand Down
Loading
Loading