-
Notifications
You must be signed in to change notification settings - Fork 2
Feat/storage nestjs module #119
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
base: main
Are you sure you want to change the base?
Conversation
Deploying utils-docs with
|
| Latest commit: |
4fe5a88
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://7673b047.utils-docs.pages.dev |
| Branch Preview URL: | https://feat-storage-nestjs-module.utils-docs.pages.dev |
Deploying rytass-utils-storybook with
|
| Latest commit: |
4fe5a88
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://c1a9d577.rytass-utils-storybook.pages.dev |
| Branch Preview URL: | https://feat-storage-nestjs-module.rytass-utils-storybook.pages.dev |
|
Overall, the current implementation of this module causes users to install packages they don’t need. This goes against the original intent of the module. Please consider an approach where all modules are declared as optionalDependencies. Since every module follows the storages root module’s contract, you should treat them all as root modules and expose optional configuration via generic types so users can inject their own types to change/infer the TypeScript tokens. In other words, the implementations inside those wrappers shouldn’t be there at all. Additionally, using constructor.name for type checks is very unsafe and should not be used that way. Please think more deeply about the role generics play in TypeScript and in this module’s design, and avoid relying on if/switch-style conditionals to implement it. |
…age-nestjs-module
…eplaced constructor.name checking with generic type, no conditionals
Feature: Standardized Storage Module (Adapter Pattern)
This PR introduces a storage integration module using the Adapter Pattern, ensuring all storage backends (GCS, S3, R2, Azure Blob, Local) present a unified, type-safe API to the rest of the application, drastically improving testability, dependency management, and type safety.
Key Features and Improvements
StorageBaseModule Enhancements
The module is now a fully featured NestJS Dynamic Module, supporting dependency injection for configuration:
forRoot<A>(options)(Synchronous): Standard setup for local or static configuration with full type inferenceforRootAsync<A>(options)(Asynchronous): Enables configuration that depends on other modules (e.g., ConfigService, database access) viauseFactory,useClass, oruseExisting. This allows us to fetch credentials and bucket names at runtimeInstanceType<A>, enabling type-safe access to adapter-specific APIsStandardized Contract (IStorageAdapter)
A new TypeScript interface (
IStorageAdapter) defines the strict contract for all storage providers:write,remove,isExists,batchWrite) have consistent signaturesurl()method with flexible signature (url?(key: string, ...args: any[]): Promise<string>) to support varying adapter requirements (GCS:url(key, expires?), S3:url(key), R2:url(key, options?))StorageService (The Public API)
The service is now a generic, type-safe business logic layer:
StorageService<A extends IStorageAdapter>preserves adapter type information for full type inferenceurl()signature:url(key: string, expires: number)) with correct type inference based on the adapterMaxFileSizeInBytes,defaultPublic, etc., and applies these checks (e.g., file size validation) before calling the adapter@Inject(STORAGE_ADAPTER) private readonly _adapter: A), making it completely independent of any concrete storage implementationOptional Dependencies Architecture
@rytass/storages-adapter-*) are declared asoptionalDependencies@rytass/storagescore packageType-Safe URL Generation
The
url()method implementation eliminates runtime type checks:constructor.namechecks: Removed unsafe runtime type checkingif/switchconditionals: Uses TypeScript generics and conditional types insteadTesting & Quality Assurance
StorageGCSService), ensuring real-world compatibilityforRootAsyncpatterns (useFactory,useClass,useExisting) are coveredurl()signatures (GCS, S3, R2, Local)Usage Example
Benefits
IStorageAdapterwith varying method signaturesBreaking Changes
StorageGCSServiceinstead ofGCSAdapter)StorageServicefor full type safetyMigration Guide
Before:
After: