@dismissible/nestjs-storage 0.0.2-canary.6b97aa7.0
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 +148 -0
- package/jest.config.ts +27 -0
- package/package.json +46 -0
- package/project.json +42 -0
- package/src/index.ts +3 -0
- package/src/memory-storage.adapter.ts +68 -0
- package/src/storage.interface.ts +34 -0
- package/src/storage.module.ts +18 -0
- package/tsconfig.json +13 -0
- package/tsconfig.lib.json +14 -0
package/README.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# @dismissible/nestjs-storage
|
|
2
|
+
|
|
3
|
+
Storage interface and in-memory adapter for the Dismissible system.
|
|
4
|
+
|
|
5
|
+
> **Part of the Dismissible API** - This library is part of the [Dismissible API](https://dismissible.io) ecosystem. Visit [dismissible.io](https://dismissible.io) for more information and documentation.
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
This library provides:
|
|
10
|
+
|
|
11
|
+
- `IDismissibleStorage` - Interface that all storage adapters must implement
|
|
12
|
+
- `MemoryStorageAdapter` - In-memory storage implementation (useful for development and testing)
|
|
13
|
+
- Storage abstraction layer for the Dismissible system
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @dismissible/nestjs-storage
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Getting Started
|
|
22
|
+
|
|
23
|
+
### Using In-Memory Storage
|
|
24
|
+
|
|
25
|
+
The in-memory storage adapter is useful for development, testing, or when you don't need persistence:
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { Module } from '@nestjs/common';
|
|
29
|
+
import { StorageModule, MemoryStorageAdapter } from '@dismissible/nestjs-storage';
|
|
30
|
+
import { LoggerModule } from '@dismissible/nestjs-logger';
|
|
31
|
+
import { DismissibleItemModule } from '@dismissible/nestjs-dismissible-item';
|
|
32
|
+
|
|
33
|
+
@Module({
|
|
34
|
+
imports: [
|
|
35
|
+
LoggerModule.forRoot({}),
|
|
36
|
+
DismissibleItemModule,
|
|
37
|
+
StorageModule.forRoot({
|
|
38
|
+
adapter: MemoryStorageAdapter,
|
|
39
|
+
}),
|
|
40
|
+
],
|
|
41
|
+
})
|
|
42
|
+
export class AppModule {}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Implementing a Custom Storage Adapter
|
|
46
|
+
|
|
47
|
+
You can implement your own storage adapter by implementing the `IDismissibleStorage` interface:
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { Injectable } from '@nestjs/common';
|
|
51
|
+
import { IDismissibleStorage, DISMISSIBLE_STORAGE_ADAPTER } from '@dismissible/nestjs-storage';
|
|
52
|
+
import { DismissibleItemDto } from '@dismissible/nestjs-dismissible-item';
|
|
53
|
+
import { DISMISSIBLE_LOGGER, IDismissibleLogger } from '@dismissible/nestjs-logger';
|
|
54
|
+
|
|
55
|
+
@Injectable()
|
|
56
|
+
export class MyCustomStorageAdapter implements IDismissibleStorage {
|
|
57
|
+
constructor(@Inject(DISMISSIBLE_LOGGER) private readonly logger: IDismissibleLogger) {}
|
|
58
|
+
|
|
59
|
+
async get(userId: string, itemId: string): Promise<DismissibleItemDto | null> {
|
|
60
|
+
// Your implementation
|
|
61
|
+
this.logger.debug('Getting item', { userId, itemId });
|
|
62
|
+
// ...
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async create(item: DismissibleItemDto): Promise<DismissibleItemDto> {
|
|
66
|
+
// Your implementation
|
|
67
|
+
this.logger.debug('Creating item', { itemId: item.id });
|
|
68
|
+
// ...
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async update(item: DismissibleItemDto): Promise<DismissibleItemDto> {
|
|
72
|
+
// Your implementation
|
|
73
|
+
this.logger.debug('Updating item', { itemId: item.id });
|
|
74
|
+
// ...
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Register your adapter
|
|
79
|
+
@Module({
|
|
80
|
+
providers: [
|
|
81
|
+
MyCustomStorageAdapter,
|
|
82
|
+
{
|
|
83
|
+
provide: DISMISSIBLE_STORAGE_ADAPTER,
|
|
84
|
+
useExisting: MyCustomStorageAdapter,
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
exports: [DISMISSIBLE_STORAGE_ADAPTER],
|
|
88
|
+
})
|
|
89
|
+
export class MyStorageModule {}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## API Reference
|
|
93
|
+
|
|
94
|
+
### IDismissibleStorage Interface
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
interface IDismissibleStorage {
|
|
98
|
+
get(userId: string, itemId: string): Promise<DismissibleItemDto | null>;
|
|
99
|
+
create(item: DismissibleItemDto): Promise<DismissibleItemDto>;
|
|
100
|
+
update(item: DismissibleItemDto): Promise<DismissibleItemDto>;
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### MemoryStorageAdapter
|
|
105
|
+
|
|
106
|
+
An in-memory implementation of `IDismissibleStorage`. Data is stored in a `Map` and will be lost when the application restarts.
|
|
107
|
+
|
|
108
|
+
**Note:** This adapter is suitable for development and testing only. For production use, consider using `@dismissible/nestjs-postgres-storage` or implementing your own persistent storage adapter.
|
|
109
|
+
|
|
110
|
+
### StorageModule
|
|
111
|
+
|
|
112
|
+
#### `StorageModule.forRoot(options)`
|
|
113
|
+
|
|
114
|
+
Configures the storage module with the provided adapter.
|
|
115
|
+
|
|
116
|
+
**Options:**
|
|
117
|
+
|
|
118
|
+
- `adapter: Type<IDismissibleStorage>` - The storage adapter class to use
|
|
119
|
+
|
|
120
|
+
**Returns:** `DynamicModule`
|
|
121
|
+
|
|
122
|
+
## Injection Token
|
|
123
|
+
|
|
124
|
+
The storage adapter is provided via the `DISMISSIBLE_STORAGE_ADAPTER` injection token:
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
import { Inject } from '@nestjs/common';
|
|
128
|
+
import { DISMISSIBLE_STORAGE_ADAPTER, IDismissibleStorage } from '@dismissible/nestjs-storage';
|
|
129
|
+
|
|
130
|
+
@Injectable()
|
|
131
|
+
export class MyService {
|
|
132
|
+
constructor(
|
|
133
|
+
@Inject(DISMISSIBLE_STORAGE_ADAPTER)
|
|
134
|
+
private readonly storage: IDismissibleStorage,
|
|
135
|
+
) {}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Related Packages
|
|
140
|
+
|
|
141
|
+
- `@dismissible/nestjs-dismissible` - Main dismissible service (uses storage adapters)
|
|
142
|
+
- `@dismissible/nestjs-postgres-storage` - PostgreSQL storage adapter implementation
|
|
143
|
+
- `@dismissible/nestjs-dismissible-item` - Data models used by storage adapters
|
|
144
|
+
- `@dismissible/nestjs-logger` - Logging used by storage adapters
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
|
|
148
|
+
MIT
|
package/jest.config.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
displayName: 'storage',
|
|
3
|
+
preset: '../../jest.preset.js',
|
|
4
|
+
testEnvironment: 'node',
|
|
5
|
+
transform: {
|
|
6
|
+
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.json' }],
|
|
7
|
+
},
|
|
8
|
+
moduleFileExtensions: ['ts', 'js', 'html'],
|
|
9
|
+
coverageDirectory: '../../coverage/libs/storage',
|
|
10
|
+
collectCoverageFrom: [
|
|
11
|
+
'src/**/*.ts',
|
|
12
|
+
'!src/**/*.spec.ts',
|
|
13
|
+
'!src/**/*.interface.ts',
|
|
14
|
+
'!src/**/*.dto.ts',
|
|
15
|
+
'!src/**/*.enum.ts',
|
|
16
|
+
'!src/**/index.ts',
|
|
17
|
+
'!src/**/*.module.ts',
|
|
18
|
+
],
|
|
19
|
+
coverageThreshold: {
|
|
20
|
+
global: {
|
|
21
|
+
branches: 80,
|
|
22
|
+
functions: 80,
|
|
23
|
+
lines: 80,
|
|
24
|
+
statements: 80,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dismissible/nestjs-storage",
|
|
3
|
+
"version": "0.0.2-canary.6b97aa7.0",
|
|
4
|
+
"description": "In-memory storage adapter for Dismissible",
|
|
5
|
+
"main": "./src/index.js",
|
|
6
|
+
"types": "./src/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./src/index.mjs",
|
|
10
|
+
"require": "./src/index.js",
|
|
11
|
+
"types": "./src/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"peerDependencies": {
|
|
15
|
+
"@nestjs/common": "^11.0.0",
|
|
16
|
+
"@dismissible/nestjs-logger": "^0.0.2-canary.6b97aa7.0",
|
|
17
|
+
"@dismissible/nestjs-dismissible-item": "^0.0.2-canary.6b97aa7.0"
|
|
18
|
+
},
|
|
19
|
+
"peerDependenciesMeta": {
|
|
20
|
+
"@nestjs/common": {
|
|
21
|
+
"optional": false
|
|
22
|
+
},
|
|
23
|
+
"@dismissible/nestjs-logger": {
|
|
24
|
+
"optional": false
|
|
25
|
+
},
|
|
26
|
+
"@dismissible/nestjs-dismissible-item": {
|
|
27
|
+
"optional": false
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"nestjs",
|
|
32
|
+
"dismissible",
|
|
33
|
+
"storage",
|
|
34
|
+
"storage",
|
|
35
|
+
"adapter"
|
|
36
|
+
],
|
|
37
|
+
"author": "",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "https://github.com/DismissibleIo/dismissible-api"
|
|
42
|
+
},
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
}
|
|
46
|
+
}
|
package/project.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "storage",
|
|
3
|
+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
+
"sourceRoot": "libs/storage/src",
|
|
5
|
+
"projectType": "library",
|
|
6
|
+
"tags": [],
|
|
7
|
+
"targets": {
|
|
8
|
+
"build": {
|
|
9
|
+
"executor": "@nx/js:tsc",
|
|
10
|
+
"outputs": ["{options.outputPath}"],
|
|
11
|
+
"options": {
|
|
12
|
+
"outputPath": "dist/libs/storage",
|
|
13
|
+
"main": "libs/storage/src/index.ts",
|
|
14
|
+
"tsConfig": "libs/storage/tsconfig.lib.json",
|
|
15
|
+
"assets": ["libs/storage/package.json", "libs/storage/README.md"],
|
|
16
|
+
"generatePackageJson": true
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"lint": {
|
|
20
|
+
"executor": "@nx/eslint:lint",
|
|
21
|
+
"outputs": ["{options.outputFile}"],
|
|
22
|
+
"options": {
|
|
23
|
+
"lintFilePatterns": ["libs/storage/**/*.ts"]
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"test": {
|
|
27
|
+
"executor": "@nx/jest:jest",
|
|
28
|
+
"outputs": ["{workspaceRoot}/coverage/libs/storage"],
|
|
29
|
+
"options": {
|
|
30
|
+
"jestConfig": "libs/storage/jest.config.ts",
|
|
31
|
+
"passWithNoTests": true
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"npm-publish": {
|
|
35
|
+
"executor": "nx:run-commands",
|
|
36
|
+
"options": {
|
|
37
|
+
"command": "npm publish --access public",
|
|
38
|
+
"cwd": "dist/libs/storage"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Injectable, Inject } from '@nestjs/common';
|
|
2
|
+
import { DISMISSIBLE_LOGGER, IDismissibleLogger } from '@dismissible/nestjs-logger';
|
|
3
|
+
import { IDismissibleStorage } from './storage.interface';
|
|
4
|
+
import { DismissibleItemDto } from '@dismissible/nestjs-dismissible-item';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* In-memory storage provider for dismissible items.
|
|
8
|
+
* Suitable for development and testing; not for production use.
|
|
9
|
+
*/
|
|
10
|
+
@Injectable()
|
|
11
|
+
export class MemoryStorageAdapter implements IDismissibleStorage {
|
|
12
|
+
private readonly storage = new Map<string, DismissibleItemDto>();
|
|
13
|
+
|
|
14
|
+
constructor(@Inject(DISMISSIBLE_LOGGER) private readonly logger: IDismissibleLogger) {}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Create a storage key from userId and itemId.
|
|
18
|
+
*/
|
|
19
|
+
private createKey(userId: string, itemId: string): string {
|
|
20
|
+
return `${userId}:${itemId}`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async get(userId: string, itemId: string): Promise<DismissibleItemDto | null> {
|
|
24
|
+
const key = this.createKey(userId, itemId);
|
|
25
|
+
this.logger.debug(`Storage get`, { userId, itemId, key });
|
|
26
|
+
|
|
27
|
+
const item = this.storage.get(key);
|
|
28
|
+
|
|
29
|
+
if (!item) {
|
|
30
|
+
this.logger.debug(`Storage miss`, { userId, itemId });
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
this.logger.debug(`Storage hit`, { userId, itemId });
|
|
35
|
+
return item;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async create(item: DismissibleItemDto): Promise<DismissibleItemDto> {
|
|
39
|
+
const key = this.createKey(item.userId, item.id);
|
|
40
|
+
this.logger.debug(`Storage create`, { userId: item.userId, itemId: item.id, key });
|
|
41
|
+
this.storage.set(key, item);
|
|
42
|
+
return item;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async update(item: DismissibleItemDto): Promise<DismissibleItemDto> {
|
|
46
|
+
const key = this.createKey(item.userId, item.id);
|
|
47
|
+
this.logger.debug(`Storage update`, { userId: item.userId, itemId: item.id, key });
|
|
48
|
+
this.storage.set(key, item);
|
|
49
|
+
return item;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Clear all stored items.
|
|
54
|
+
* Useful for testing.
|
|
55
|
+
*/
|
|
56
|
+
clear(): void {
|
|
57
|
+
this.logger.debug(`Storage clear`, { previousSize: this.storage.size });
|
|
58
|
+
this.storage.clear();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Get the number of stored items.
|
|
63
|
+
* Useful for testing/debugging.
|
|
64
|
+
*/
|
|
65
|
+
get size(): number {
|
|
66
|
+
return this.storage.size;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { DismissibleItemDto } from '@dismissible/nestjs-dismissible-item';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Injection token for the storage provider.
|
|
5
|
+
*/
|
|
6
|
+
export const DISMISSIBLE_STORAGE_ADAPTER = Symbol('DISMISSIBLE_STORAGE_ADAPTER');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Interface for storage providers.
|
|
10
|
+
* Implementations handle the persistence of dismissible items.
|
|
11
|
+
*/
|
|
12
|
+
export interface IDismissibleStorage {
|
|
13
|
+
/**
|
|
14
|
+
* Retrieve an item by user ID and item ID.
|
|
15
|
+
* @param userId The user identifier
|
|
16
|
+
* @param itemId The item identifier
|
|
17
|
+
* @returns The item or null if not found
|
|
18
|
+
*/
|
|
19
|
+
get(userId: string, itemId: string): Promise<DismissibleItemDto | null>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Create a new item.
|
|
23
|
+
* @param item The item to create (contains userId and id)
|
|
24
|
+
* @returns The created item
|
|
25
|
+
*/
|
|
26
|
+
create(item: DismissibleItemDto): Promise<DismissibleItemDto>;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Update an existing item.
|
|
30
|
+
* @param item The item to update (contains userId and id)
|
|
31
|
+
* @returns The updated item
|
|
32
|
+
*/
|
|
33
|
+
update(item: DismissibleItemDto): Promise<DismissibleItemDto>;
|
|
34
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { DynamicModule, Module, Type } from '@nestjs/common';
|
|
2
|
+
import { DISMISSIBLE_STORAGE_ADAPTER } from './storage.interface';
|
|
3
|
+
import { MemoryStorageAdapter } from './memory-storage.adapter';
|
|
4
|
+
|
|
5
|
+
export type IDismissibleStorageModuleOptions = {
|
|
6
|
+
storage?: Type<any> | DynamicModule;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
@Module({
|
|
10
|
+
providers: [
|
|
11
|
+
{
|
|
12
|
+
provide: DISMISSIBLE_STORAGE_ADAPTER,
|
|
13
|
+
useClass: MemoryStorageAdapter,
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
exports: [DISMISSIBLE_STORAGE_ADAPTER],
|
|
17
|
+
})
|
|
18
|
+
export class StorageModule {}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "../../dist/out-tsc",
|
|
5
|
+
"declaration": true,
|
|
6
|
+
"module": "commonjs",
|
|
7
|
+
"types": ["node"],
|
|
8
|
+
"emitDecoratorMetadata": true,
|
|
9
|
+
"experimentalDecorators": true,
|
|
10
|
+
"target": "ES2021"
|
|
11
|
+
},
|
|
12
|
+
"exclude": ["node_modules", "**/*.spec.ts", "**/*.test.ts"],
|
|
13
|
+
"include": ["src/**/*.ts"]
|
|
14
|
+
}
|