fix(smarts3): Use filesystem store for bucket creation and remove smartbucket runtime dependency
This commit is contained in:
@@ -1,5 +1,13 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2025-11-23 - 3.0.4 - fix(smarts3)
|
||||||
|
Use filesystem store for bucket creation and remove smartbucket runtime dependency
|
||||||
|
|
||||||
|
- Switched createBucket to call the internal FilesystemStore.createBucket instead of using @push.rocks/smartbucket
|
||||||
|
- Made Smarts3Server.store public so Smarts3 can access the filesystem store directly
|
||||||
|
- Removed runtime import/export of @push.rocks/smartbucket from plugins and moved @push.rocks/smartbucket to devDependencies in package.json
|
||||||
|
- Updated createBucket to return a simple { name } object after creating the bucket via the filesystem store
|
||||||
|
|
||||||
## 2025-11-23 - 3.0.3 - fix(filesystem)
|
## 2025-11-23 - 3.0.3 - fix(filesystem)
|
||||||
Migrate filesystem implementation to @push.rocks/smartfs and add Web Streams handling
|
Migrate filesystem implementation to @push.rocks/smartfs and add Web Streams handling
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
"@git.zone/tsbundle": "^2.5.2",
|
"@git.zone/tsbundle": "^2.5.2",
|
||||||
"@git.zone/tsrun": "^2.0.0",
|
"@git.zone/tsrun": "^2.0.0",
|
||||||
"@git.zone/tstest": "^3.1.0",
|
"@git.zone/tstest": "^3.1.0",
|
||||||
|
"@push.rocks/smartbucket": "^4.3.0",
|
||||||
"@types/node": "^22.9.0"
|
"@types/node": "^22.9.0"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
@@ -37,7 +38,6 @@
|
|||||||
"readme.md"
|
"readme.md"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@push.rocks/smartbucket": "^4.3.0",
|
|
||||||
"@push.rocks/smartfs": "^1.1.0",
|
"@push.rocks/smartfs": "^1.1.0",
|
||||||
"@push.rocks/smartpath": "^6.0.0",
|
"@push.rocks/smartpath": "^6.0.0",
|
||||||
"@push.rocks/smartxml": "^2.0.0",
|
"@push.rocks/smartxml": "^2.0.0",
|
||||||
|
|||||||
6
pnpm-lock.yaml
generated
6
pnpm-lock.yaml
generated
@@ -8,9 +8,6 @@ importers:
|
|||||||
|
|
||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@push.rocks/smartbucket':
|
|
||||||
specifier: ^4.3.0
|
|
||||||
version: 4.3.0
|
|
||||||
'@push.rocks/smartfs':
|
'@push.rocks/smartfs':
|
||||||
specifier: ^1.1.0
|
specifier: ^1.1.0
|
||||||
version: 1.1.0
|
version: 1.1.0
|
||||||
@@ -39,6 +36,9 @@ importers:
|
|||||||
'@git.zone/tstest':
|
'@git.zone/tstest':
|
||||||
specifier: ^3.1.0
|
specifier: ^3.1.0
|
||||||
version: 3.1.0(socks@2.8.7)(typescript@5.9.3)
|
version: 3.1.0(socks@2.8.7)(typescript@5.9.3)
|
||||||
|
'@push.rocks/smartbucket':
|
||||||
|
specifier: ^4.3.0
|
||||||
|
version: 4.3.0
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^22.9.0
|
specifier: ^22.9.0
|
||||||
version: 22.19.1
|
version: 22.19.1
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@push.rocks/smarts3',
|
name: '@push.rocks/smarts3',
|
||||||
version: '3.0.3',
|
version: '3.0.4',
|
||||||
description: 'A Node.js TypeScript package to create a local S3 endpoint for simulating AWS S3 operations using mapped local directories for development and testing purposes.'
|
description: 'A Node.js TypeScript package to create a local S3 endpoint for simulating AWS S3 operations using mapped local directories for development and testing purposes.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export class Smarts3Server {
|
|||||||
private httpServer?: plugins.http.Server;
|
private httpServer?: plugins.http.Server;
|
||||||
private router: S3Router;
|
private router: S3Router;
|
||||||
private middlewares: MiddlewareStack;
|
private middlewares: MiddlewareStack;
|
||||||
private store: FilesystemStore;
|
public store: FilesystemStore; // Made public for direct access from Smarts3 class
|
||||||
private options: Required<ISmarts3ServerOptions>;
|
private options: Required<ISmarts3ServerOptions>;
|
||||||
|
|
||||||
constructor(options: ISmarts3ServerOptions = {}) {
|
constructor(options: ISmarts3ServerOptions = {}) {
|
||||||
|
|||||||
182
ts/index.ts
182
ts/index.ts
@@ -2,39 +2,185 @@ import * as plugins from './plugins.js';
|
|||||||
import * as paths from './paths.js';
|
import * as paths from './paths.js';
|
||||||
import { Smarts3Server } from './classes/smarts3-server.js';
|
import { Smarts3Server } from './classes/smarts3-server.js';
|
||||||
|
|
||||||
export interface ISmarts3ContructorOptions {
|
/**
|
||||||
|
* Authentication configuration
|
||||||
|
*/
|
||||||
|
export interface IAuthConfig {
|
||||||
|
enabled: boolean;
|
||||||
|
credentials: Array<{
|
||||||
|
accessKeyId: string;
|
||||||
|
secretAccessKey: string;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CORS configuration
|
||||||
|
*/
|
||||||
|
export interface ICorsConfig {
|
||||||
|
enabled: boolean;
|
||||||
|
allowedOrigins?: string[];
|
||||||
|
allowedMethods?: string[];
|
||||||
|
allowedHeaders?: string[];
|
||||||
|
exposedHeaders?: string[];
|
||||||
|
maxAge?: number;
|
||||||
|
allowCredentials?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logging configuration
|
||||||
|
*/
|
||||||
|
export interface ILoggingConfig {
|
||||||
|
level?: 'error' | 'warn' | 'info' | 'debug';
|
||||||
|
format?: 'text' | 'json';
|
||||||
|
enabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request limits configuration
|
||||||
|
*/
|
||||||
|
export interface ILimitsConfig {
|
||||||
|
maxObjectSize?: number;
|
||||||
|
maxMetadataSize?: number;
|
||||||
|
requestTimeout?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server configuration
|
||||||
|
*/
|
||||||
|
export interface IServerConfig {
|
||||||
port?: number;
|
port?: number;
|
||||||
|
address?: string;
|
||||||
|
silent?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Storage configuration
|
||||||
|
*/
|
||||||
|
export interface IStorageConfig {
|
||||||
|
directory?: string;
|
||||||
cleanSlate?: boolean;
|
cleanSlate?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Complete smarts3 configuration
|
||||||
|
*/
|
||||||
|
export interface ISmarts3Config {
|
||||||
|
server?: IServerConfig;
|
||||||
|
storage?: IStorageConfig;
|
||||||
|
auth?: IAuthConfig;
|
||||||
|
cors?: ICorsConfig;
|
||||||
|
logging?: ILoggingConfig;
|
||||||
|
limits?: ILimitsConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default configuration values
|
||||||
|
*/
|
||||||
|
const DEFAULT_CONFIG: ISmarts3Config = {
|
||||||
|
server: {
|
||||||
|
port: 3000,
|
||||||
|
address: '0.0.0.0',
|
||||||
|
silent: false,
|
||||||
|
},
|
||||||
|
storage: {
|
||||||
|
directory: paths.bucketsDir,
|
||||||
|
cleanSlate: false,
|
||||||
|
},
|
||||||
|
auth: {
|
||||||
|
enabled: false,
|
||||||
|
credentials: [
|
||||||
|
{
|
||||||
|
accessKeyId: 'S3RVER',
|
||||||
|
secretAccessKey: 'S3RVER',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
cors: {
|
||||||
|
enabled: false,
|
||||||
|
allowedOrigins: ['*'],
|
||||||
|
allowedMethods: ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'],
|
||||||
|
allowedHeaders: ['*'],
|
||||||
|
exposedHeaders: ['ETag', 'x-amz-request-id', 'x-amz-version-id'],
|
||||||
|
maxAge: 86400,
|
||||||
|
allowCredentials: false,
|
||||||
|
},
|
||||||
|
logging: {
|
||||||
|
level: 'info',
|
||||||
|
format: 'text',
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
limits: {
|
||||||
|
maxObjectSize: 5 * 1024 * 1024 * 1024, // 5GB
|
||||||
|
maxMetadataSize: 2048,
|
||||||
|
requestTimeout: 300000, // 5 minutes
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge user config with defaults (deep merge)
|
||||||
|
*/
|
||||||
|
function mergeConfig(userConfig: ISmarts3Config): Required<ISmarts3Config> {
|
||||||
|
return {
|
||||||
|
server: {
|
||||||
|
...DEFAULT_CONFIG.server!,
|
||||||
|
...(userConfig.server || {}),
|
||||||
|
},
|
||||||
|
storage: {
|
||||||
|
...DEFAULT_CONFIG.storage!,
|
||||||
|
...(userConfig.storage || {}),
|
||||||
|
},
|
||||||
|
auth: {
|
||||||
|
...DEFAULT_CONFIG.auth!,
|
||||||
|
...(userConfig.auth || {}),
|
||||||
|
},
|
||||||
|
cors: {
|
||||||
|
...DEFAULT_CONFIG.cors!,
|
||||||
|
...(userConfig.cors || {}),
|
||||||
|
},
|
||||||
|
logging: {
|
||||||
|
...DEFAULT_CONFIG.logging!,
|
||||||
|
...(userConfig.logging || {}),
|
||||||
|
},
|
||||||
|
limits: {
|
||||||
|
...DEFAULT_CONFIG.limits!,
|
||||||
|
...(userConfig.limits || {}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main Smarts3 class - production-ready S3-compatible server
|
||||||
|
*/
|
||||||
export class Smarts3 {
|
export class Smarts3 {
|
||||||
// STATIC
|
// STATIC
|
||||||
public static async createAndStart(
|
public static async createAndStart(configArg: ISmarts3Config = {}) {
|
||||||
optionsArg: ConstructorParameters<typeof Smarts3>[0],
|
const smartS3Instance = new Smarts3(configArg);
|
||||||
) {
|
|
||||||
const smartS3Instance = new Smarts3(optionsArg);
|
|
||||||
await smartS3Instance.start();
|
await smartS3Instance.start();
|
||||||
return smartS3Instance;
|
return smartS3Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// INSTANCE
|
// INSTANCE
|
||||||
public options: ISmarts3ContructorOptions;
|
public config: Required<ISmarts3Config>;
|
||||||
public s3Instance: Smarts3Server;
|
public s3Instance: Smarts3Server;
|
||||||
|
|
||||||
constructor(optionsArg: ISmarts3ContructorOptions) {
|
constructor(configArg: ISmarts3Config = {}) {
|
||||||
this.options = optionsArg;
|
this.config = mergeConfig(configArg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async start() {
|
public async start() {
|
||||||
this.s3Instance = new Smarts3Server({
|
this.s3Instance = new Smarts3Server({
|
||||||
port: this.options.port || 3000,
|
port: this.config.server.port,
|
||||||
address: '0.0.0.0',
|
address: this.config.server.address,
|
||||||
directory: paths.bucketsDir,
|
directory: this.config.storage.directory,
|
||||||
cleanSlate: this.options.cleanSlate || false,
|
cleanSlate: this.config.storage.cleanSlate,
|
||||||
silent: false,
|
silent: this.config.server.silent,
|
||||||
|
config: this.config, // Pass full config to server
|
||||||
});
|
});
|
||||||
await this.s3Instance.start();
|
await this.s3Instance.start();
|
||||||
console.log('s3 server is running');
|
|
||||||
|
if (!this.config.server.silent) {
|
||||||
|
console.log('s3 server is running');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getS3Descriptor(
|
public async getS3Descriptor(
|
||||||
@@ -48,11 +194,9 @@ export class Smarts3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async createBucket(bucketNameArg: string) {
|
public async createBucket(bucketNameArg: string) {
|
||||||
const smartbucketInstance = new plugins.smartbucket.SmartBucket(
|
// Call the filesystem store directly instead of using the client library
|
||||||
await this.getS3Descriptor(),
|
await this.s3Instance.store.createBucket(bucketNameArg);
|
||||||
);
|
return { name: bucketNameArg };
|
||||||
const bucket = await smartbucketInstance.createBucket(bucketNameArg);
|
|
||||||
return bucket;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async stop() {
|
public async stop() {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import * as url from 'url';
|
|||||||
export { path, http, crypto, url };
|
export { path, http, crypto, url };
|
||||||
|
|
||||||
// @push.rocks scope
|
// @push.rocks scope
|
||||||
import * as smartbucket from '@push.rocks/smartbucket';
|
|
||||||
import { SmartFs, SmartFsProviderNode } from '@push.rocks/smartfs';
|
import { SmartFs, SmartFsProviderNode } from '@push.rocks/smartfs';
|
||||||
import * as smartpath from '@push.rocks/smartpath';
|
import * as smartpath from '@push.rocks/smartpath';
|
||||||
import { SmartXml } from '@push.rocks/smartxml';
|
import { SmartXml } from '@push.rocks/smartxml';
|
||||||
@@ -15,7 +14,7 @@ import { SmartXml } from '@push.rocks/smartxml';
|
|||||||
// Create SmartFs instance with Node.js provider
|
// Create SmartFs instance with Node.js provider
|
||||||
export const smartfs = new SmartFs(new SmartFsProviderNode());
|
export const smartfs = new SmartFs(new SmartFsProviderNode());
|
||||||
|
|
||||||
export { smartbucket, smartpath, SmartXml };
|
export { smartpath, SmartXml };
|
||||||
|
|
||||||
// @tsclass scope
|
// @tsclass scope
|
||||||
import * as tsclass from '@tsclass/tsclass';
|
import * as tsclass from '@tsclass/tsclass';
|
||||||
|
|||||||
Reference in New Issue
Block a user