
Research
/Security News
DuckDB npm Account Compromised in Continuing Supply Chain Attack
Ongoing npm supply chain attack spreads to DuckDB: multiple packages compromised with the same wallet-drainer malware.
@neoxia-js/nestjs-storage
Advanced tools
nestjs module allawing communication with different kind of local and cloud storage
This package allow the management of your projects uploaded files using differents strategies
yarn add @neoxia-js/nestjs-storage
Create an entity which extends the package storage.entity.ts
import { Entity, OneToMany } from 'typeorm';
import {
Storage as StorageBase,
StorageInterface,
} from '@neoxia-js/nestjs-storage';
import { User } from '../user/user.entity';
@Entity()
export class Storage extends StorageBase implements StorageInterface {}
this entity is the one where all your files informations will be stored, you have to put a relation between the original entity that needs the file and the storage entity
// user.entity.ts
import { Entity, Column, PrimaryGeneratedColumn, ManyToOne } from 'typeorm';
import { Storage } from '../storage/storage.entity';
@Entity()
export class User {
// ...
@OneToOne(() => Storage, { eager: true, cascade: true })
@JoinColumn()
thumbnail: Storage;
}
import the storage module in app.module.ts
, you can use the exported multer config from StorageService to initialize the MulterModule
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { MulterModule } from '@nestjs/platform-express';
import {
StorageModule,
StorageModuleConfig,
StorageService,
} from '@neoxia-js/nestjs-storage';
import { MulterOptions } from '@nestjs/platform-express/multer/interfaces/multer-options.interface';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
load: [databaseConfig, storageConfig],
envFilePath: !ENV ? '.env' : `.env.${ENV}`,
}),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) =>
configService.get('database'),
inject: [ConfigService],
}),
StorageModule.registerAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService): StorageModuleConfig =>
configService.get('storage'),
inject: [ConfigService],
}),
MulterModule.registerAsync({
imports: [StorageModule],
useFactory: (storageService: StorageService): MulterOptions =>
storageService.getMulterConfig(),
inject: [StorageService],
}),
do not forget to import the ServeStaticModule
if the used strategy is local
(and if you need it)
// app.moduke.ts
@Module({
imports: [
// ...
ServeStaticModule.forRoot({
rootPath: join(process.cwd(), '.', 'public'),
}),
})
here is un example of StorageModuleConfig
// src/config/storage.config.ts
import { registerAs } from '@nestjs/config';
import { StorageModuleConfig, STORAGE_KINDS } from '@neoxia-js/nestjs-storage';
export default registerAs('storage', (): StorageModuleConfig => ({
defaultFileSystem: process.env.FILE_SYSTEM || STORAGE_KINDS.LOCAL,
maxFileSize: parseInt(process.env.MAX_FILE_SIZE),
fileSystems: {
someLocalFileSystem: {
strategy: STORAGE_KINDS.LOCAL,
baseUrl: process.env.BASE_URL || 'http://localhost',
publicDir: process.env.PUBLIC_DIR || 'public',
destinationDir: process.env.STORAGE_DIR || 'storage',
},
someAzurePrivateFileSystem: {
strategy: STORAGE_KINDS.AZURE,
connectionString: process.env.AZURE_STORAGE_CONNECTION_STRING,
container: process.env.AZURE_STORAGE_CONTAINER,
sasTime: parseInt(process.env.AZURE_SAS_TIME),
isPublic: false,
},
azurePublicFileSystem: {
strategy: STORAGE_KINDS.AZURE,
connectionString: process.env.AZURE_STORAGE_CONNECTION_STRING,
container: process.env.AZURE_STORAGE_PUBLIC_CONTAINER,
isPublic: true,
},
},
}));
now the multer configuration used by the FileInterceptor will be the one retrived by the storageService.getMulterConfig()
and every eagered storage entity will have at least the properties
fieldname
originalname
mimetype
path
url
the function getMulterConfig
accepts the fileSystem name as argument, default is the defaultFileSystem
where url is the autogenerated (not in database) url of the media
this url is also generated using the shaed access signature
(only for azure strategy for now), allowing the url to be public for a short period of time
{
defaultFileSystem: "someLocalFileSystem", // fileSystem kind, it must be one of the "fileSystems" key property
maxFileSize: 8000000, // max file size in bytes, default 8000000
fileSystems: {
someLocalFileSystem: {
strategy: "local", // only "local" or "azure" for now
baseUrl: 'http://localhost', // url of the server
publicDir: 'public', // server public directory, default 'public'
destinationDir: 'storage', // server image directory inside publiic directory, default 'storage'
},
someAzureFileSystem: {
strategy: "azure", // only "local" or "azure" for now
connectionString: "", // azure bucket connection string
container: "", // azure bucket container name
sasTime: 100, // azue public sas url time validity (in minutes) default 100
isPublic: false, // the container (and so the image) is publicly accessible or not
// even if the property is set to true, but the container already exists and it is private,
// the image won't be publicly accessible
},
}
}
FAQs
nestjs module allawing communication with different kind of local and cloud storage
We found that @neoxia-js/nestjs-storage demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 9 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
/Security News
Ongoing npm supply chain attack spreads to DuckDB: multiple packages compromised with the same wallet-drainer malware.
Security News
The MCP Steering Committee has launched the official MCP Registry in preview, a central hub for discovering and publishing MCP servers.
Product
Socket’s new Pull Request Stories give security teams clear visibility into dependency risks and outcomes across scanned pull requests.