@theshelf/filestore 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,64 +9,57 @@ The file store package provides a universal interaction layer with an actual fil
9
9
  npm install @theshelf/filestore
10
10
  ```
11
11
 
12
- ## Implementations
12
+ ## Drivers
13
13
 
14
- Currently, there are two implementations:
14
+ Currently, there are two drivers available:
15
15
 
16
16
  * **Memory** - non-persistent in memory storage (suited for testing).
17
17
  * **Minio** - persistent S3 compatible object storage.
18
18
 
19
- ## Configuration
19
+ ## How to use
20
20
 
21
- The used implementation needs to be configured in the `.env` file.
21
+ The basic set up looks like this.
22
22
 
23
- ```env
24
- FILE_STORE_IMPLEMENTATION="minio" # (memory | minio)
25
- ```
23
+ ```ts
24
+ import FileStore, { MemoryDriver | MinioDriver as SelectedDriver } from '@theshelf/fileStore';
26
25
 
27
- In case of Minio, additional configuration is required.
26
+ const driver = new SelectedDriver(/* configuration */);
27
+ const fileStore = new FileStore(driver);
28
28
 
29
- ```env
30
- MINIO_END_POINT="address"
31
- MINIO_PORT_NUMBER=9000
32
- MINIO_USE_SSL=true
33
- MINIO_ACCESS_KEY="development"
34
- MINIO_SECRET_KEY="secret"
29
+ // Perform operations with the fileStore instance
35
30
  ```
36
31
 
37
- ## How to use
32
+ ### Configuration
38
33
 
39
- An instance of the configured file storage implementation can be imported for performing file operations.
34
+ #### Memory driver
40
35
 
41
- ```ts
42
- import fileStorage from '@theshelf/filestorage';
36
+ No configuration options.
43
37
 
44
- // Perform operations with the fileStorage instance
45
- ```
38
+ #### Minio driver
39
+
40
+ The `ClientOptions` from the 'minio' package.
46
41
 
47
42
  ### Operations
48
43
 
49
44
  ```ts
50
- import fileStorage from '@theshelf/filestorage';
51
-
52
45
  // Open connection
53
- await fileStorage.connect();
46
+ await fileStore.connect();
54
47
 
55
48
  // Close connection
56
- await fileStorage.disconnect();
49
+ await fileStore.disconnect();
57
50
 
58
51
  // Check if a file exists
59
- const exists: boolean = await fileStorage.hasFile('path/to/file.txt');
52
+ const exists: boolean = await fileStore.hasFile('path/to/file.txt');
60
53
 
61
54
  // Write a file to the storage
62
55
  const data: Buffer = Buffer.from('Something interesting');
63
- await fileStorage.writeFile('path/to/file.txt', data);
56
+ await fileStore.writeFile('path/to/file.txt', data);
64
57
 
65
58
  // Read a file from storage
66
59
  // Throws FileNotFound if not found
67
- const data: Buffer = await fileStorage.readFile('path/to/file.txt');
60
+ const data: Buffer = await fileStore.readFile('path/to/file.txt');
68
61
 
69
62
  // Delete a file from storage
70
63
  // Throws FileNotFound if not found
71
- await fileStorage.deleteFile('path/to/file.txt');
64
+ await fileStore.deleteFile('path/to/file.txt');
72
65
  ```
@@ -0,0 +1,9 @@
1
+ import type { ConnectionState } from './definitions/constants.js';
2
+ import type { Driver } from './definitions/interfaces.js';
3
+ export default class ConnectionManager {
4
+ #private;
5
+ constructor(driver: Driver);
6
+ get state(): ConnectionState;
7
+ connect(): Promise<void>;
8
+ disconnect(): Promise<void>;
9
+ }
@@ -0,0 +1,53 @@
1
+ import { ConnectionStates } from './definitions/constants.js';
2
+ export default class ConnectionManager {
3
+ #driver;
4
+ #state = ConnectionStates.DISCONNECTED;
5
+ #connectPromise;
6
+ #disconnectPromise;
7
+ constructor(driver) {
8
+ this.#driver = driver;
9
+ }
10
+ get state() { return this.#state; }
11
+ async connect() {
12
+ if (this.#connectPromise !== undefined) {
13
+ return this.#connectPromise;
14
+ }
15
+ if (this.#state !== ConnectionStates.DISCONNECTED) {
16
+ return;
17
+ }
18
+ this.#state = ConnectionStates.CONNECTING;
19
+ try {
20
+ this.#connectPromise = this.#driver.connect();
21
+ await this.#connectPromise;
22
+ this.#state = ConnectionStates.CONNECTED;
23
+ }
24
+ catch (error) {
25
+ this.#state = ConnectionStates.DISCONNECTED;
26
+ throw error;
27
+ }
28
+ finally {
29
+ this.#connectPromise = undefined;
30
+ }
31
+ }
32
+ async disconnect() {
33
+ if (this.#disconnectPromise !== undefined) {
34
+ return this.#disconnectPromise;
35
+ }
36
+ if (this.#state !== ConnectionStates.CONNECTED) {
37
+ return;
38
+ }
39
+ this.#state = ConnectionStates.DISCONNECTING;
40
+ try {
41
+ this.#disconnectPromise = this.#driver.disconnect();
42
+ await this.#disconnectPromise;
43
+ this.#state = ConnectionStates.DISCONNECTED;
44
+ }
45
+ catch (error) {
46
+ this.#state = ConnectionStates.CONNECTED;
47
+ throw error;
48
+ }
49
+ finally {
50
+ this.#disconnectPromise = undefined;
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,14 @@
1
+ import type { ConnectionState } from './definitions/constants.js';
2
+ import type { Driver } from './definitions/interfaces.js';
3
+ export default class FileStore implements Driver {
4
+ #private;
5
+ constructor(driver: Driver);
6
+ get connectionState(): ConnectionState;
7
+ get connected(): boolean;
8
+ connect(): Promise<void>;
9
+ disconnect(): Promise<void>;
10
+ hasFile(path: string): Promise<boolean>;
11
+ writeFile(path: string, data: Buffer): Promise<void>;
12
+ readFile(path: string): Promise<Buffer>;
13
+ deleteFile(path: string): Promise<void>;
14
+ }
@@ -0,0 +1,34 @@
1
+ import { ConnectionStates } from './definitions/constants.js';
2
+ import ConnectionManager from './ConnectionManager.js';
3
+ export default class FileStore {
4
+ #driver;
5
+ #connectionManager;
6
+ constructor(driver) {
7
+ this.#driver = driver;
8
+ this.#connectionManager = new ConnectionManager(driver);
9
+ }
10
+ get connectionState() {
11
+ return this.#connectionManager.state;
12
+ }
13
+ get connected() {
14
+ return this.connectionState === ConnectionStates.CONNECTED;
15
+ }
16
+ connect() {
17
+ return this.#connectionManager.connect();
18
+ }
19
+ disconnect() {
20
+ return this.#connectionManager.disconnect();
21
+ }
22
+ hasFile(path) {
23
+ return this.#driver.hasFile(path);
24
+ }
25
+ writeFile(path, data) {
26
+ return this.#driver.writeFile(path, data);
27
+ }
28
+ readFile(path) {
29
+ return this.#driver.readFile(path);
30
+ }
31
+ deleteFile(path) {
32
+ return this.#driver.deleteFile(path);
33
+ }
34
+ }
@@ -0,0 +1,7 @@
1
+ export declare const ConnectionStates: {
2
+ readonly DISCONNECTED: "DISCONNECTED";
3
+ readonly DISCONNECTING: "DISCONNECTING";
4
+ readonly CONNECTING: "CONNECTING";
5
+ readonly CONNECTED: "CONNECTED";
6
+ };
7
+ export type ConnectionState = typeof ConnectionStates[keyof typeof ConnectionStates];
@@ -0,0 +1,6 @@
1
+ export const ConnectionStates = {
2
+ DISCONNECTED: 'DISCONNECTED',
3
+ DISCONNECTING: 'DISCONNECTING',
4
+ CONNECTING: 'CONNECTING',
5
+ CONNECTED: 'CONNECTED'
6
+ };
@@ -1,4 +1,4 @@
1
- export interface FileStore {
1
+ export interface Driver {
2
2
  get connected(): boolean;
3
3
  connect(): Promise<void>;
4
4
  disconnect(): Promise<void>;
@@ -6,5 +6,4 @@ export interface FileStore {
6
6
  writeFile(path: string, data: Buffer): Promise<void>;
7
7
  readFile(path: string): Promise<Buffer>;
8
8
  deleteFile(path: string): Promise<void>;
9
- clear(): Promise<void>;
10
9
  }
@@ -1,12 +1,13 @@
1
- import type { FileStore } from '../../definitions/interfaces.js';
2
- export default class Memory implements FileStore {
1
+ import type { Driver } from '../definitions/interfaces.js';
2
+ export default class Memory implements Driver {
3
3
  #private;
4
4
  get connected(): boolean;
5
+ get files(): Map<string, Buffer>;
5
6
  connect(): Promise<void>;
6
7
  disconnect(): Promise<void>;
7
8
  hasFile(path: string): Promise<boolean>;
8
9
  writeFile(path: string, data: Buffer): Promise<void>;
9
10
  readFile(path: string): Promise<Buffer>;
10
11
  deleteFile(path: string): Promise<void>;
11
- clear(): Promise<void>;
12
+ clear(): void;
12
13
  }
@@ -1,45 +1,42 @@
1
- import FileNotFound from '../../errors/FileNotFound.js';
2
- import NotConnected from '../../errors/NotConnected.js';
1
+ import NotConnected from '../errors/NotConnected.js';
2
+ import FileNotFound from '../errors/FileNotFound.js';
3
3
  export default class Memory {
4
4
  #files = new Map();
5
5
  #connected = false;
6
6
  get connected() { return this.#connected; }
7
+ get files() {
8
+ if (this.#connected === false) {
9
+ throw new NotConnected();
10
+ }
11
+ return this.#files;
12
+ }
7
13
  async connect() {
8
14
  this.#connected = true;
9
15
  }
10
16
  async disconnect() {
11
17
  this.#connected = false;
18
+ this.#files.clear();
12
19
  }
13
20
  async hasFile(path) {
14
- const files = this.#getFiles();
15
- return files.has(path);
21
+ return this.files.has(path);
16
22
  }
17
23
  async writeFile(path, data) {
18
- const files = this.#getFiles();
19
- files.set(path, data);
24
+ this.files.set(path, data);
20
25
  }
21
26
  async readFile(path) {
22
- const files = this.#getFiles();
23
- const data = files.get(path);
27
+ const data = this.files.get(path);
24
28
  if (data === undefined) {
25
29
  throw new FileNotFound(path);
26
30
  }
27
31
  return data;
28
32
  }
29
33
  async deleteFile(path) {
30
- const files = this.#getFiles();
31
- if (files.has(path) === false) {
34
+ if (this.files.has(path) === false) {
32
35
  throw new FileNotFound(path);
33
36
  }
34
- files.delete(path);
37
+ this.files.delete(path);
35
38
  }
36
- #getFiles() {
37
- if (this.#files === undefined) {
38
- throw new NotConnected();
39
- }
40
- return this.#files;
41
- }
42
- async clear() {
43
- this.#files.clear();
39
+ clear() {
40
+ this.files.clear();
44
41
  }
45
42
  }
@@ -1,6 +1,6 @@
1
1
  import type { ClientOptions } from 'minio';
2
- import type { FileStore } from '../../definitions/interfaces.js';
3
- export default class MinioFS implements FileStore {
2
+ import type { Driver } from '../definitions/interfaces.js';
3
+ export default class Minio implements Driver {
4
4
  #private;
5
5
  constructor(configuration: ClientOptions);
6
6
  get connected(): boolean;
@@ -10,5 +10,4 @@ export default class MinioFS implements FileStore {
10
10
  writeFile(path: string, data: Buffer): Promise<void>;
11
11
  readFile(path: string): Promise<Buffer>;
12
12
  deleteFile(path: string): Promise<void>;
13
- clear(): Promise<void>;
14
13
  }
@@ -1,8 +1,8 @@
1
1
  import { Client } from 'minio';
2
- import FileNotFound from '../../errors/FileNotFound.js';
3
- import NotConnected from '../../errors/NotConnected.js';
2
+ import FileNotFound from '../errors/FileNotFound.js';
3
+ import NotConnected from '../errors/NotConnected.js';
4
4
  const BUCKET_NAME = 'comify';
5
- export default class MinioFS {
5
+ export default class Minio {
6
6
  #configuration;
7
7
  #client;
8
8
  constructor(configuration) {
@@ -66,9 +66,6 @@ export default class MinioFS {
66
66
  throw this.#handleError(error, path);
67
67
  }
68
68
  }
69
- async clear() {
70
- return; // Deliberately not implemented
71
- }
72
69
  #getClient() {
73
70
  if (this.#client === undefined) {
74
71
  throw new NotConnected();
@@ -1,4 +1,4 @@
1
- import FileSystemError from './FileSystemError.js';
2
- export default class FileNotFound extends FileSystemError {
1
+ import FileStoreError from './FileStoreError.js';
2
+ export default class FileNotFound extends FileStoreError {
3
3
  constructor(path?: string);
4
4
  }
@@ -1,5 +1,5 @@
1
- import FileSystemError from './FileSystemError.js';
2
- export default class FileNotFound extends FileSystemError {
1
+ import FileStoreError from './FileStoreError.js';
2
+ export default class FileNotFound extends FileStoreError {
3
3
  constructor(path) {
4
4
  super(path ? `File not found: ${path}` : 'File not found');
5
5
  }
@@ -0,0 +1,3 @@
1
+ export default class FileStoreError extends Error {
2
+ constructor(message?: string);
3
+ }
@@ -0,0 +1,9 @@
1
+ export default class FileStoreError extends Error {
2
+ constructor(message) {
3
+ super(message);
4
+ this.name = this.constructor.name;
5
+ if (Error.captureStackTrace) {
6
+ Error.captureStackTrace(this, this.constructor);
7
+ }
8
+ }
9
+ }
@@ -1,4 +1,4 @@
1
- import FileSystemError from './FileSystemError.js';
2
- export default class NotConnected extends FileSystemError {
3
- constructor(message?: string);
1
+ import FileStoreError from './FileStoreError.js';
2
+ export default class NotConnected extends FileStoreError {
3
+ constructor();
4
4
  }
@@ -1,6 +1,6 @@
1
- import FileSystemError from './FileSystemError.js';
2
- export default class NotConnected extends FileSystemError {
3
- constructor(message) {
4
- super(message ?? 'File system not connected');
1
+ import FileStoreError from './FileStoreError.js';
2
+ export default class NotConnected extends FileStoreError {
3
+ constructor() {
4
+ super('File store not connected');
5
5
  }
6
6
  }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- export type { FileStore } from './definitions/interfaces.js';
1
+ export type * from './definitions/interfaces.js';
2
2
  export { default as FileNotFound } from './errors/FileNotFound.js';
3
- export { default as FileSystemError } from './errors/FileSystemError.js';
3
+ export { default as FileSystemError } from './errors/FileStoreError.js';
4
4
  export { default as NotConnected } from './errors/NotConnected.js';
5
- export { default as UnknownImplementation } from './errors/UnknownImplementation.js';
6
- export { default } from './implementation.js';
5
+ export { default as MemoryDriver } from './drivers/Memory.js';
6
+ export { default as MinioDriver } from './drivers/Minio.js';
7
+ export { default } from './FileStore.js';
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { default as FileNotFound } from './errors/FileNotFound.js';
2
- export { default as FileSystemError } from './errors/FileSystemError.js';
2
+ export { default as FileSystemError } from './errors/FileStoreError.js';
3
3
  export { default as NotConnected } from './errors/NotConnected.js';
4
- export { default as UnknownImplementation } from './errors/UnknownImplementation.js';
5
- export { default } from './implementation.js';
4
+ export { default as MemoryDriver } from './drivers/Memory.js';
5
+ export { default as MinioDriver } from './drivers/Minio.js';
6
+ export { default } from './FileStore.js';
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@theshelf/filestore",
3
3
  "private": false,
4
- "version": "0.1.0",
4
+ "version": "0.2.1",
5
5
  "type": "module",
6
6
  "repository": {
7
- "url": "https://github.com/MaskingTechnology/theshelf"
7
+ "url": "git+https://github.com/MaskingTechnology/theshelf.git"
8
8
  },
9
9
  "scripts": {
10
10
  "build": "tsc",
@@ -1,2 +0,0 @@
1
- export default class FileSystemError extends Error {
2
- }
@@ -1,2 +0,0 @@
1
- export default class FileSystemError extends Error {
2
- }
@@ -1,4 +0,0 @@
1
- import FileSystemError from './FileSystemError.js';
2
- export default class UnknownImplementation extends FileSystemError {
3
- constructor(name: string);
4
- }
@@ -1,6 +0,0 @@
1
- import FileSystemError from './FileSystemError.js';
2
- export default class UnknownImplementation extends FileSystemError {
3
- constructor(name) {
4
- super(`Unknown file system implementation: ${name}`);
5
- }
6
- }
@@ -1,3 +0,0 @@
1
- import type { FileStore } from './definitions/interfaces.js';
2
- declare const _default: FileStore;
3
- export default _default;
@@ -1,14 +0,0 @@
1
- import UnknownImplementation from './errors/UnknownImplementation.js';
2
- import createMemoryFS from './implementations/memory/create.js';
3
- import createMinioFS from './implementations/minio/create.js';
4
- const implementations = new Map([
5
- ['memory', createMemoryFS],
6
- ['minio', createMinioFS],
7
- ]);
8
- const DEFAULT_FILE_STORE_IMPLEMENTATION = 'memory';
9
- const implementationName = process.env.FILE_STORE_IMPLEMENTATION ?? DEFAULT_FILE_STORE_IMPLEMENTATION;
10
- const creator = implementations.get(implementationName.toLowerCase());
11
- if (creator === undefined) {
12
- throw new UnknownImplementation(implementationName);
13
- }
14
- export default creator();
@@ -1,2 +0,0 @@
1
- import Memory from './Memory.js';
2
- export default function create(): Memory;
@@ -1,4 +0,0 @@
1
- import Memory from './Memory.js';
2
- export default function create() {
3
- return new Memory();
4
- }
@@ -1,2 +0,0 @@
1
- import MinioFS from './MinioFS.js';
2
- export default function create(): MinioFS;
@@ -1,9 +0,0 @@
1
- import MinioFS from './MinioFS.js';
2
- export default function create() {
3
- const endPoint = process.env.MINIO_END_POINT ?? 'undefined';
4
- const port = Number(process.env.MINIO_PORT_NUMBER ?? 9000);
5
- const useSSL = process.env.MINIO_USE_SSL === 'true';
6
- const accessKey = process.env.MINIO_ROOT_USER ?? 'undefined';
7
- const secretKey = process.env.MINIO_ROOT_PASSWORD ?? 'undefined';
8
- return new MinioFS({ endPoint, port, useSSL, accessKey, secretKey });
9
- }