mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
fix: refactoring of storage method
This commit is contained in:
@@ -7,7 +7,7 @@ services:
|
||||
# context: .
|
||||
# dockerfile: docker/dockerfile/Dockerfile
|
||||
# target: prod
|
||||
image: solucetechnologies/portabase:1.2.2-rc.2
|
||||
image: solucetechnologies/portabase:latest
|
||||
ports:
|
||||
- '8887:80'
|
||||
environment:
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
"react-twc": "^1.4.2",
|
||||
"react-use-measure": "^2.1.7",
|
||||
"recharts": "^2.15.3",
|
||||
"sharp": "^0.34.5",
|
||||
"socket.io": "^4.8.1",
|
||||
"socket.io-client": "^4.8.1",
|
||||
"sonner": "^2.0.3",
|
||||
|
||||
Generated
+20
-18
@@ -124,7 +124,7 @@ importers:
|
||||
version: 6.0.0
|
||||
better-auth:
|
||||
specifier: 1.4.5
|
||||
version: 1.4.5(next@16.0.10(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
version: 1.4.5(next@16.0.10(@babel/core@7.26.10)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
class-variance-authority:
|
||||
specifier: ^0.7.1
|
||||
version: 0.7.1
|
||||
@@ -169,10 +169,10 @@ importers:
|
||||
version: 12.24.7(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
next:
|
||||
specifier: 16.0.10
|
||||
version: 16.0.10(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
version: 16.0.10(@babel/core@7.26.10)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
next-safe-action:
|
||||
specifier: ^7.10.8
|
||||
version: 7.10.8(next@16.0.10(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.25.76)
|
||||
version: 7.10.8(next@16.0.10(@babel/core@7.26.10)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.25.76)
|
||||
next-themes:
|
||||
specifier: ^0.4.6
|
||||
version: 0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
@@ -227,6 +227,9 @@ importers:
|
||||
recharts:
|
||||
specifier: ^2.15.3
|
||||
version: 2.15.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
sharp:
|
||||
specifier: ^0.34.5
|
||||
version: 0.34.5
|
||||
socket.io:
|
||||
specifier: ^4.8.1
|
||||
version: 4.8.3
|
||||
@@ -10133,7 +10136,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/node': 22.19.3
|
||||
tapable: 2.3.0
|
||||
webpack: 5.104.1(esbuild@0.27.2)
|
||||
webpack: 5.104.1(esbuild@0.25.10)
|
||||
transitivePeerDependencies:
|
||||
- '@swc/core'
|
||||
- esbuild
|
||||
@@ -10730,7 +10733,7 @@ snapshots:
|
||||
|
||||
bcryptjs@2.4.3: {}
|
||||
|
||||
better-auth@1.4.5(next@16.0.10(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
|
||||
better-auth@1.4.5(next@16.0.10(@babel/core@7.26.10)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
|
||||
dependencies:
|
||||
'@better-auth/core': 1.4.5(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.1.4(zod@3.25.76))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0)
|
||||
'@better-auth/telemetry': 1.4.5(@better-auth/core@1.4.5(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.1.4(zod@3.25.76))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0))
|
||||
@@ -10746,7 +10749,7 @@ snapshots:
|
||||
nanostores: 1.1.0
|
||||
zod: 4.3.5
|
||||
optionalDependencies:
|
||||
next: 16.0.10(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
next: 16.0.10(@babel/core@7.26.10)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
react: 19.2.3
|
||||
react-dom: 19.2.3(react@19.2.3)
|
||||
|
||||
@@ -12660,9 +12663,9 @@ snapshots:
|
||||
|
||||
neo-async@2.6.2: {}
|
||||
|
||||
next-safe-action@7.10.8(next@16.0.10(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.25.76):
|
||||
next-safe-action@7.10.8(next@16.0.10(@babel/core@7.26.10)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.25.76):
|
||||
dependencies:
|
||||
next: 16.0.10(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
next: 16.0.10(@babel/core@7.26.10)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
react: 19.2.3
|
||||
react-dom: 19.2.3(react@19.2.3)
|
||||
optionalDependencies:
|
||||
@@ -12691,12 +12694,12 @@ snapshots:
|
||||
'@next/swc-linux-x64-musl': 15.5.2
|
||||
'@next/swc-win32-arm64-msvc': 15.5.2
|
||||
'@next/swc-win32-x64-msvc': 15.5.2
|
||||
sharp: 0.34.4
|
||||
sharp: 0.34.5
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- babel-plugin-macros
|
||||
|
||||
next@16.0.10(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
|
||||
next@16.0.10(@babel/core@7.26.10)(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
|
||||
dependencies:
|
||||
'@next/env': 16.0.10
|
||||
'@swc/helpers': 0.5.15
|
||||
@@ -12704,7 +12707,7 @@ snapshots:
|
||||
postcss: 8.4.31
|
||||
react: 19.2.3
|
||||
react-dom: 19.2.3(react@19.2.3)
|
||||
styled-jsx: 5.1.6(@babel/core@7.28.5)(react@19.2.3)
|
||||
styled-jsx: 5.1.6(@babel/core@7.26.10)(react@19.2.3)
|
||||
optionalDependencies:
|
||||
'@next/swc-darwin-arm64': 16.0.10
|
||||
'@next/swc-darwin-x64': 16.0.10
|
||||
@@ -13531,7 +13534,6 @@ snapshots:
|
||||
'@img/sharp-win32-arm64': 0.34.5
|
||||
'@img/sharp-win32-ia32': 0.34.5
|
||||
'@img/sharp-win32-x64': 0.34.5
|
||||
optional: true
|
||||
|
||||
shebang-command@2.0.0:
|
||||
dependencies:
|
||||
@@ -13785,12 +13787,12 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@babel/core': 7.26.10
|
||||
|
||||
styled-jsx@5.1.6(@babel/core@7.28.5)(react@19.2.3):
|
||||
styled-jsx@5.1.6(@babel/core@7.26.10)(react@19.2.3):
|
||||
dependencies:
|
||||
client-only: 0.0.1
|
||||
react: 19.2.3
|
||||
optionalDependencies:
|
||||
'@babel/core': 7.28.5
|
||||
'@babel/core': 7.26.10
|
||||
|
||||
sucrase@3.35.1:
|
||||
dependencies:
|
||||
@@ -13878,14 +13880,14 @@ snapshots:
|
||||
ansi-escapes: 4.3.2
|
||||
supports-hyperlinks: 2.3.0
|
||||
|
||||
terser-webpack-plugin@5.3.16(esbuild@0.25.10)(webpack@5.104.1(esbuild@0.25.10)):
|
||||
terser-webpack-plugin@5.3.16(esbuild@0.25.10)(webpack@5.104.1(esbuild@0.27.2)):
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.31
|
||||
jest-worker: 27.5.1
|
||||
schema-utils: 4.3.3
|
||||
serialize-javascript: 6.0.2
|
||||
terser: 5.44.1
|
||||
webpack: 5.104.1(esbuild@0.27.2)
|
||||
webpack: 5.104.1(esbuild@0.25.10)
|
||||
optionalDependencies:
|
||||
esbuild: 0.25.10
|
||||
|
||||
@@ -14240,7 +14242,7 @@ snapshots:
|
||||
|
||||
webpack-sources@3.3.3: {}
|
||||
|
||||
webpack@5.104.1(esbuild@0.27.2):
|
||||
webpack@5.104.1(esbuild@0.25.10):
|
||||
dependencies:
|
||||
'@types/eslint-scope': 3.7.7
|
||||
'@types/estree': 1.0.8
|
||||
@@ -14264,7 +14266,7 @@ snapshots:
|
||||
neo-async: 2.6.2
|
||||
schema-utils: 4.3.3
|
||||
tapable: 2.3.0
|
||||
terser-webpack-plugin: 5.3.16(esbuild@0.25.10)(webpack@5.104.1(esbuild@0.25.10))
|
||||
terser-webpack-plugin: 5.3.16(esbuild@0.25.10)(webpack@5.104.1(esbuild@0.27.2))
|
||||
watchpack: 2.5.0
|
||||
webpack-sources: 3.3.3
|
||||
transitivePeerDependencies:
|
||||
|
||||
@@ -48,14 +48,25 @@ export const AvatarWithUpload = (props: AvatarWithUploadProps) => {
|
||||
const handleImageUpload = async (event: ChangeEvent<HTMLInputElement>) => {
|
||||
const file = event.target.files?.[0];
|
||||
if (!file) return;
|
||||
if (!file.type.includes("image")) {
|
||||
toast.error("File not an image");
|
||||
|
||||
const allowedFormats = ["image/jpeg", "image/png", "image/webp"];
|
||||
|
||||
if (!allowedFormats.includes(file.type)) {
|
||||
toast.error("Only JPG, PNG or WebP images are allowed.");
|
||||
return;
|
||||
}
|
||||
|
||||
const maxSizeInMB = 5;
|
||||
if (file.size > maxSizeInMB * 1024 * 1024) {
|
||||
toast.error(`Image must be smaller than ${maxSizeInMB}MB.`);
|
||||
return;
|
||||
}
|
||||
|
||||
submitImage.mutate(file);
|
||||
};
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div className="relative ">
|
||||
|
||||
@@ -68,7 +79,7 @@ export const AvatarWithUpload = (props: AvatarWithUploadProps) => {
|
||||
onClick={() => {
|
||||
const fileInput = document.createElement("input");
|
||||
fileInput.type = "file";
|
||||
fileInput.accept = "image/*";
|
||||
fileInput.accept = ".jpg,.jpeg,.png,.webp";
|
||||
// @ts-ignore
|
||||
fileInput.onchange = handleImageUpload;
|
||||
fileInput.click();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as Minio from "minio";
|
||||
import {StorageDeleteInput, StorageGetInput, StorageResult, StorageUploadInput} from "../types";
|
||||
import {getServerUrl} from "@/utils/get-server-url";
|
||||
import {StorageDeleteInput, StorageGetInput, StorageMetaData, StorageResult, StorageUploadInput} from "../types";
|
||||
import {generateFileUrl} from "@/features/storages/helpers";
|
||||
|
||||
type S3Config = {
|
||||
endPointUrl: string;
|
||||
@@ -30,7 +30,10 @@ async function ensureBucket(config: S3Config) {
|
||||
if (!exists) await client.makeBucket(config.bucketName);
|
||||
}
|
||||
|
||||
export async function uploadS3(config: S3Config, input: { data: StorageUploadInput }): Promise<StorageResult> {
|
||||
export async function uploadS3(
|
||||
config: S3Config,
|
||||
input: { data: StorageUploadInput, metadata?: StorageMetaData }
|
||||
): Promise<StorageResult> {
|
||||
const client = await getS3Client(config);
|
||||
await ensureBucket(config);
|
||||
|
||||
@@ -44,16 +47,32 @@ export async function uploadS3(config: S3Config, input: { data: StorageUploadInp
|
||||
}
|
||||
|
||||
await client.putObject(config.bucketName, key, input.data.file as Buffer);
|
||||
const baseUrl = getServerUrl();
|
||||
|
||||
|
||||
if (input.data.url) {
|
||||
const url = await generateFileUrl(input);
|
||||
if (!url) {
|
||||
return {
|
||||
success: false,
|
||||
provider: "s3",
|
||||
response: "Unable to get url file"
|
||||
};
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
provider: 's3',
|
||||
url: url
|
||||
};
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
provider: 's3',
|
||||
url: `${baseUrl}/api/${input.data.path}`,
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
export async function getS3(config: S3Config, input: { data: StorageGetInput }): Promise<StorageResult> {
|
||||
export async function getS3(config: S3Config, input: { data: StorageGetInput, metadata: StorageMetaData }): Promise<StorageResult> {
|
||||
const client = await getS3Client(config);
|
||||
|
||||
const key = `${BASE_DIR}${input.data.path}`;
|
||||
@@ -78,9 +97,8 @@ export async function getS3(config: S3Config, input: { data: StorageGetInput }):
|
||||
};
|
||||
}
|
||||
|
||||
export async function deleteS3(config: S3Config, input: { data: StorageDeleteInput }): Promise<StorageResult> {
|
||||
export async function deleteS3(config: S3Config, input: { data: StorageDeleteInput, metadata?: StorageMetaData }): Promise<StorageResult> {
|
||||
const client = await getS3Client(config);
|
||||
// const key = input.data.path;
|
||||
const key = `${BASE_DIR}${input.data.path}`;
|
||||
|
||||
try {
|
||||
|
||||
@@ -8,6 +8,7 @@ import * as drizzleDb from "@/db";
|
||||
import {ServerActionResult} from "@/types/action-type";
|
||||
import {dispatchStorage} from "@/features/storages/dispatch";
|
||||
import {StorageInput} from "@/features/storages/types";
|
||||
import sharp from "sharp";
|
||||
|
||||
|
||||
export const uploadUserImageAction = userAction.schema(
|
||||
@@ -22,6 +23,19 @@ export const uploadUserImageAction = userAction.schema(
|
||||
const buffer = Buffer.from(arrayBuffer);
|
||||
|
||||
|
||||
const isPng = fileFormat === "png";
|
||||
const isWebp = fileFormat === "webp";
|
||||
|
||||
const compressedBuffer = await sharp(buffer)
|
||||
.resize({ width: 1024 })
|
||||
.toFormat(isPng ? "png" : isWebp ? "webp" : "jpeg", {
|
||||
quality: 80,
|
||||
compressionLevel: isPng ? 9 : undefined
|
||||
})
|
||||
.toBuffer();
|
||||
|
||||
|
||||
|
||||
const settings = await db.query.setting.findFirst({
|
||||
where: eq(drizzleDb.schemas.setting.name, "system"),
|
||||
with: {
|
||||
@@ -45,7 +59,7 @@ export const uploadUserImageAction = userAction.schema(
|
||||
action: "upload",
|
||||
data: {
|
||||
path: path,
|
||||
file: buffer,
|
||||
file: compressedBuffer,
|
||||
url: true
|
||||
},
|
||||
metadata: {
|
||||
|
||||
Reference in New Issue
Block a user