@nauth-toolkit/storage-database 0.1.3
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/LICENSE +90 -0
- package/README.md +147 -0
- package/dist/database-storage.adapter.d.ts +35 -0
- package/dist/database-storage.adapter.d.ts.map +1 -0
- package/dist/database-storage.adapter.js +496 -0
- package/dist/database-storage.adapter.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
NAUTH TOOLKIT EARLY ACCESS LICENSE
|
|
2
|
+
Version 1.0 (December 2025)
|
|
3
|
+
|
|
4
|
+
================================================================================
|
|
5
|
+
FUTURE OPEN SOURCE NOTICE
|
|
6
|
+
================================================================================
|
|
7
|
+
NAuth Toolkit will transition to an open-source license (MIT or Apache 2.0) for
|
|
8
|
+
core authentication features once the project reaches production readiness.
|
|
9
|
+
|
|
10
|
+
This Early Access License is temporary and designed to:
|
|
11
|
+
• Allow developers to build with nauth-toolkit during preview/beta
|
|
12
|
+
• Provide clear expectations during the pre-release phase
|
|
13
|
+
• Enable feedback and real-world testing before GA
|
|
14
|
+
|
|
15
|
+
We're committed to keeping core auth free and open source. Premium features
|
|
16
|
+
(enterprise SSO, advanced compliance, hosted options) will be offered separately
|
|
17
|
+
under fair commercial terms.
|
|
18
|
+
|
|
19
|
+
================================================================================
|
|
20
|
+
EARLY ACCESS LICENSE TERMS
|
|
21
|
+
================================================================================
|
|
22
|
+
|
|
23
|
+
1. Grant of Use
|
|
24
|
+
You are granted a free, non-exclusive, non-transferable license to:
|
|
25
|
+
- Install and use nauth-toolkit packages in development, testing, staging,
|
|
26
|
+
and production environments
|
|
27
|
+
- Modify the code for your own internal use
|
|
28
|
+
- Deploy applications using nauth-toolkit to serve your users
|
|
29
|
+
|
|
30
|
+
You may NOT:
|
|
31
|
+
- Redistribute NAuth Toolkit as a standalone product or service
|
|
32
|
+
- Sell, sublicense, or offer NAuth Toolkit as part of a competing auth
|
|
33
|
+
platform or toolkit
|
|
34
|
+
- Remove or alter copyright notices
|
|
35
|
+
|
|
36
|
+
2. No Fees During Early Access
|
|
37
|
+
There are no license fees, subscription costs, or usage charges during the
|
|
38
|
+
Early Access period. You may use nauth-toolkit freely for commercial and
|
|
39
|
+
non-commercial purposes within the terms of this license.
|
|
40
|
+
|
|
41
|
+
3. Production Use
|
|
42
|
+
Production use is permitted but comes with standard early-access caveats:
|
|
43
|
+
- Features and APIs may change between preview releases
|
|
44
|
+
- Support is community-based (GitHub issues/discussions)
|
|
45
|
+
- No SLA or guaranteed uptime (you run it on your infrastructure)
|
|
46
|
+
|
|
47
|
+
We recommend thorough testing and having rollback plans for critical systems.
|
|
48
|
+
|
|
49
|
+
4. Future Transition
|
|
50
|
+
When nauth-toolkit releases v1.0 GA:
|
|
51
|
+
- Core packages will adopt an open-source license (MIT or Apache 2.0)
|
|
52
|
+
- Your existing deployments will continue to work
|
|
53
|
+
- Premium features (if any) will be clearly documented with separate licensing
|
|
54
|
+
- No forced upgrades or surprise fees
|
|
55
|
+
|
|
56
|
+
5. Ownership
|
|
57
|
+
NAuth Toolkit is developed and maintained by Noorix Digital Solutions.
|
|
58
|
+
You retain full ownership of your applications and data.
|
|
59
|
+
|
|
60
|
+
6. Data and Privacy
|
|
61
|
+
NAuth Toolkit runs in YOUR infrastructure and database. You control all data.
|
|
62
|
+
You are responsible for compliance with applicable data protection laws.
|
|
63
|
+
|
|
64
|
+
7. Disclaimer of Warranty
|
|
65
|
+
THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
66
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
67
|
+
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
|
|
68
|
+
|
|
69
|
+
8. Limitation of Liability
|
|
70
|
+
IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
|
|
71
|
+
SPECIAL, CONSEQUENTIAL, OR EXEMPLARY DAMAGES, INCLUDING BUT NOT LIMITED TO LOSS
|
|
72
|
+
OF PROFITS, REVENUE, DATA, OR USE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
73
|
+
DAMAGES.
|
|
74
|
+
|
|
75
|
+
9. Termination
|
|
76
|
+
This license remains in effect until:
|
|
77
|
+
- You stop using nauth-toolkit, or
|
|
78
|
+
- The project transitions to open source (at which point the new license applies)
|
|
79
|
+
|
|
80
|
+
If you breach these terms, your license terminates and you must stop using the
|
|
81
|
+
software.
|
|
82
|
+
|
|
83
|
+
10. Contact and Support
|
|
84
|
+
- Documentation: https://nauth.dev
|
|
85
|
+
- Issues/Discussions: GitHub (when public repository launches)
|
|
86
|
+
- Commercial inquiries: Contact admin@noorix.com
|
|
87
|
+
|
|
88
|
+
================================================================================
|
|
89
|
+
Thank you for being an early adopter. Your feedback shapes the future of NAuth.
|
|
90
|
+
================================================================================
|
package/README.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# @nauth-toolkit/storage-database
|
|
2
|
+
|
|
3
|
+
Database storage adapter for nauth-toolkit using TypeORM repositories.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`DatabaseStorageAdapter` implements the `StorageAdapter` interface using your existing TypeORM connection. It stores transient state (rate limits, distributed locks, token reuse tracking) in database tables, making it perfect for multi-server deployments without requiring Redis.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- ✅ **Multi-server compatible** - All servers share the same database
|
|
12
|
+
- ✅ **No separate connection** - Uses your existing TypeORM DataSource
|
|
13
|
+
- ✅ **Atomic operations** - Database-level increment/decrement for thread-safety
|
|
14
|
+
- ✅ **TTL support** - Automatic expiration via `expiresAt` column
|
|
15
|
+
- ✅ **PostgreSQL & MySQL** - Works with both database types
|
|
16
|
+
- ✅ **Zero external dependencies** - No Redis required
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
yarn add @nauth-toolkit/storage-database
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
### 1. Include Storage Entities
|
|
27
|
+
|
|
28
|
+
Storage entities (`RateLimit`, `StorageLock`) must be included in your TypeORM configuration:
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { getNAuthEntities, getNAuthStorageEntities } from '@nauth-toolkit/database-typeorm-postgres';
|
|
32
|
+
// or
|
|
33
|
+
// import { getNAuthEntities, getNAuthStorageEntities } from '@nauth-toolkit/database-typeorm-mysql';
|
|
34
|
+
|
|
35
|
+
@Module({
|
|
36
|
+
imports: [
|
|
37
|
+
TypeOrmModule.forRoot({
|
|
38
|
+
type: 'postgres', // or 'mysql'
|
|
39
|
+
// ... your DB config
|
|
40
|
+
entities: [
|
|
41
|
+
...getNAuthEntities(), // Core entities (User, Session, etc.)
|
|
42
|
+
...getNAuthStorageEntities(), // Storage entities (RateLimit, StorageLock)
|
|
43
|
+
],
|
|
44
|
+
}),
|
|
45
|
+
AuthModule.forRoot({
|
|
46
|
+
jwt: { ... },
|
|
47
|
+
storageAdapter: new DatabaseStorageAdapter(),
|
|
48
|
+
}),
|
|
49
|
+
],
|
|
50
|
+
})
|
|
51
|
+
export class AppModule {}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 2. Configure Storage Adapter
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { DatabaseStorageAdapter } from '@nauth-toolkit/storage-database';
|
|
58
|
+
|
|
59
|
+
AuthModule.forRoot({
|
|
60
|
+
jwt: { ... },
|
|
61
|
+
storageAdapter: new DatabaseStorageAdapter(),
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The adapter automatically injects `RateLimitRepository` and `StorageLockRepository` via NestJS dependency injection.
|
|
66
|
+
|
|
67
|
+
## Database Tables
|
|
68
|
+
|
|
69
|
+
The adapter creates two tables:
|
|
70
|
+
|
|
71
|
+
### `nauth_rate_limits`
|
|
72
|
+
|
|
73
|
+
Stores rate limit counters and key-value pairs.
|
|
74
|
+
|
|
75
|
+
**Schema:**
|
|
76
|
+
- `id`: Primary key
|
|
77
|
+
- `key`: VARCHAR(255) UNIQUE - Storage key
|
|
78
|
+
- `value`: TEXT - Stored value (counter or JSON)
|
|
79
|
+
- `expiresAt`: TIMESTAMP - Expiration time
|
|
80
|
+
- `createdAt`: TIMESTAMP
|
|
81
|
+
- `updatedAt`: TIMESTAMP
|
|
82
|
+
|
|
83
|
+
**Indexes:**
|
|
84
|
+
- `idx_rate_limits_key` (UNIQUE) on `key`
|
|
85
|
+
- `idx_rate_limits_expires` on `expiresAt`
|
|
86
|
+
|
|
87
|
+
### `nauth_storage_locks`
|
|
88
|
+
|
|
89
|
+
Stores distributed locks for concurrent operations.
|
|
90
|
+
|
|
91
|
+
**Schema:**
|
|
92
|
+
- `id`: Primary key
|
|
93
|
+
- `key`: VARCHAR(255) UNIQUE - Lock key
|
|
94
|
+
- `value`: TEXT - Lock value
|
|
95
|
+
- `expiresAt`: TIMESTAMP - Lock expiration
|
|
96
|
+
- `createdAt`: TIMESTAMP
|
|
97
|
+
|
|
98
|
+
**Indexes:**
|
|
99
|
+
- `idx_storage_locks_key` (UNIQUE) on `key`
|
|
100
|
+
- `idx_storage_locks_expires` on `expiresAt`
|
|
101
|
+
|
|
102
|
+
## Cleanup
|
|
103
|
+
|
|
104
|
+
Expired records are cleaned up via:
|
|
105
|
+
|
|
106
|
+
1. **Automatic expiration** - Queries check `expiresAt` and delete expired records
|
|
107
|
+
2. **Scheduled cleanup** - Run `adapter.cleanup()` periodically or set up a database-level scheduled job
|
|
108
|
+
|
|
109
|
+
**PostgreSQL (pg_cron):**
|
|
110
|
+
```sql
|
|
111
|
+
SELECT cron.schedule(
|
|
112
|
+
'cleanup-expired-storage',
|
|
113
|
+
'*/5 * * * *', -- Every 5 minutes
|
|
114
|
+
'DELETE FROM nauth_rate_limits WHERE expiresAt < NOW(); DELETE FROM nauth_storage_locks WHERE expiresAt < NOW();'
|
|
115
|
+
);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**MySQL (EVENT SCHEDULER):**
|
|
119
|
+
```sql
|
|
120
|
+
CREATE EVENT cleanup_expired_storage
|
|
121
|
+
ON SCHEDULE EVERY 5 MINUTE
|
|
122
|
+
DO
|
|
123
|
+
DELETE FROM nauth_rate_limits WHERE expiresAt < NOW();
|
|
124
|
+
DELETE FROM nauth_storage_locks WHERE expiresAt < NOW();
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Performance Considerations
|
|
128
|
+
|
|
129
|
+
- **Atomic operations** use database-level `UPDATE ... SET value = value + 1` for optimal concurrency
|
|
130
|
+
- **Indexes** on `key` and `expiresAt` ensure fast lookups
|
|
131
|
+
- **Hash/list operations** stored as JSON in the `value` column
|
|
132
|
+
- **Cleanup** should run periodically to prevent table bloat
|
|
133
|
+
|
|
134
|
+
## Comparison with Other Adapters
|
|
135
|
+
|
|
136
|
+
| Feature | MemoryStorageAdapter | DatabaseStorageAdapter | RedisStorageAdapter |
|
|
137
|
+
|---------|---------------------|------------------------|---------------------|
|
|
138
|
+
| Multi-server | ❌ | ✅ | ✅ |
|
|
139
|
+
| Persistence | ❌ | ✅ | ✅ (optional) |
|
|
140
|
+
| Performance | ⚡⚡⚡ | ⚡⚡ | ⚡⚡⚡ |
|
|
141
|
+
| External dependency | ❌ | ❌ | ✅ (Redis) |
|
|
142
|
+
| Setup complexity | 🟢 Low | 🟡 Medium | 🟡 Medium |
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
MIT
|
|
147
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Repository } from 'typeorm';
|
|
2
|
+
import { StorageAdapter, LoggerService, BaseRateLimit, BaseStorageLock } from '@nauth-toolkit/core';
|
|
3
|
+
export declare class DatabaseStorageAdapter implements StorageAdapter {
|
|
4
|
+
private rateLimitRepo;
|
|
5
|
+
private storageLockRepo;
|
|
6
|
+
private logger?;
|
|
7
|
+
constructor(rateLimitRepo: Repository<BaseRateLimit> | null, storageLockRepo: Repository<BaseStorageLock> | null, logger?: LoggerService | undefined);
|
|
8
|
+
setRepositories(rateLimitRepo: Repository<BaseRateLimit>, storageLockRepo: Repository<BaseStorageLock>): void;
|
|
9
|
+
private getRepositoryForKey;
|
|
10
|
+
initialize(): Promise<void>;
|
|
11
|
+
isHealthy(): Promise<boolean>;
|
|
12
|
+
get(key: string): Promise<string | null>;
|
|
13
|
+
set(key: string, value: string, ttlSeconds?: number, options?: {
|
|
14
|
+
nx?: boolean;
|
|
15
|
+
}): Promise<string | null>;
|
|
16
|
+
del(key: string): Promise<void>;
|
|
17
|
+
exists(key: string): Promise<boolean>;
|
|
18
|
+
incr(key: string, ttlSeconds?: number): Promise<number>;
|
|
19
|
+
decr(key: string): Promise<number>;
|
|
20
|
+
expire(key: string, ttlSeconds: number): Promise<void>;
|
|
21
|
+
private getDbNowPlusSecondsExpression;
|
|
22
|
+
ttl(key: string): Promise<number>;
|
|
23
|
+
hset(key: string, field: string, value: string): Promise<void>;
|
|
24
|
+
hget(key: string, field: string): Promise<string | null>;
|
|
25
|
+
hgetall(key: string): Promise<Record<string, string>>;
|
|
26
|
+
hdel(key: string, ...fields: string[]): Promise<number>;
|
|
27
|
+
lpush(key: string, value: string): Promise<void>;
|
|
28
|
+
lrange(key: string, start: number, stop: number): Promise<string[]>;
|
|
29
|
+
llen(key: string): Promise<number>;
|
|
30
|
+
keys(pattern: string): Promise<string[]>;
|
|
31
|
+
scan(cursor: number, pattern: string, count: number): Promise<[number, string[]]>;
|
|
32
|
+
cleanup(): Promise<void>;
|
|
33
|
+
disconnect(): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=database-storage.adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-storage.adapter.d.ts","sourceRoot":"","sources":["../src/database-storage.adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DatabaseStorageAdapter = void 0;
|
|
4
|
+
const typeorm_1 = require("typeorm");
|
|
5
|
+
class DatabaseStorageAdapter {
|
|
6
|
+
rateLimitRepo;
|
|
7
|
+
storageLockRepo;
|
|
8
|
+
logger;
|
|
9
|
+
constructor(rateLimitRepo, storageLockRepo, logger) {
|
|
10
|
+
this.rateLimitRepo = rateLimitRepo;
|
|
11
|
+
this.storageLockRepo = storageLockRepo;
|
|
12
|
+
this.logger = logger;
|
|
13
|
+
}
|
|
14
|
+
setRepositories(rateLimitRepo, storageLockRepo) {
|
|
15
|
+
this.rateLimitRepo = rateLimitRepo;
|
|
16
|
+
this.storageLockRepo = storageLockRepo;
|
|
17
|
+
}
|
|
18
|
+
getRepositoryForKey(key) {
|
|
19
|
+
if (key.startsWith('refresh-lock:') || key.startsWith('used-token:') || key.startsWith('session-refresh:')) {
|
|
20
|
+
return this.storageLockRepo;
|
|
21
|
+
}
|
|
22
|
+
return this.rateLimitRepo;
|
|
23
|
+
}
|
|
24
|
+
async initialize() {
|
|
25
|
+
if (!this.rateLimitRepo || !this.storageLockRepo) {
|
|
26
|
+
throw new Error('DatabaseStorageAdapter requires RateLimit and StorageLock repositories to be registered. ' +
|
|
27
|
+
'Make sure to include storage entities in TypeORM.forRoot(): ' +
|
|
28
|
+
'entities: [...getNAuthEntities(), ...getNAuthStorageEntities()]');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async isHealthy() {
|
|
32
|
+
return !!(this.rateLimitRepo && this.storageLockRepo);
|
|
33
|
+
}
|
|
34
|
+
async get(key) {
|
|
35
|
+
try {
|
|
36
|
+
const repo = this.getRepositoryForKey(key);
|
|
37
|
+
const record = await repo.findOne({
|
|
38
|
+
where: { key },
|
|
39
|
+
});
|
|
40
|
+
if (!record) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const expiresAt = record.expiresAt;
|
|
44
|
+
if (expiresAt && expiresAt < new Date()) {
|
|
45
|
+
await repo.delete({ key });
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
return record.value;
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
this.logger?.error?.(`Failed to get key ${key}:`, error);
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async set(key, value, ttlSeconds, options) {
|
|
56
|
+
const now = new Date();
|
|
57
|
+
const expiresAt = ttlSeconds ? new Date(now.getTime() + ttlSeconds * 1000) : null;
|
|
58
|
+
try {
|
|
59
|
+
const repo = this.getRepositoryForKey(key);
|
|
60
|
+
if (options?.nx) {
|
|
61
|
+
try {
|
|
62
|
+
await repo
|
|
63
|
+
.createQueryBuilder()
|
|
64
|
+
.insert()
|
|
65
|
+
.into(repo.target)
|
|
66
|
+
.values({
|
|
67
|
+
key,
|
|
68
|
+
value,
|
|
69
|
+
expiresAt,
|
|
70
|
+
})
|
|
71
|
+
.execute();
|
|
72
|
+
return value;
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
const dbError = error;
|
|
76
|
+
const isDuplicateKey = dbError.code === 'ER_DUP_ENTRY' ||
|
|
77
|
+
dbError.code === '23505' ||
|
|
78
|
+
dbError.message?.includes('duplicate key') ||
|
|
79
|
+
dbError.message?.includes('UNIQUE constraint failed');
|
|
80
|
+
if (!isDuplicateKey) {
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
return await repo.manager.transaction(async (transactionalEntityManager) => {
|
|
84
|
+
const existing = await transactionalEntityManager.findOne(repo.target, {
|
|
85
|
+
where: { key },
|
|
86
|
+
lock: { mode: 'pessimistic_write' },
|
|
87
|
+
});
|
|
88
|
+
if (!existing) {
|
|
89
|
+
try {
|
|
90
|
+
await transactionalEntityManager.insert(repo.target, {
|
|
91
|
+
key,
|
|
92
|
+
value,
|
|
93
|
+
expiresAt,
|
|
94
|
+
});
|
|
95
|
+
return value;
|
|
96
|
+
}
|
|
97
|
+
catch (retryError) {
|
|
98
|
+
const retryDbError = retryError;
|
|
99
|
+
if (retryDbError.code === 'ER_DUP_ENTRY' ||
|
|
100
|
+
retryDbError.code === '23505' ||
|
|
101
|
+
retryDbError.message?.includes('duplicate key') ||
|
|
102
|
+
retryDbError.message?.includes('UNIQUE constraint failed')) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
throw retryError;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const existingExpiresAt = existing.expiresAt;
|
|
109
|
+
if (existingExpiresAt && existingExpiresAt < now) {
|
|
110
|
+
await transactionalEntityManager.delete(repo.target, { key });
|
|
111
|
+
await transactionalEntityManager.insert(repo.target, {
|
|
112
|
+
key,
|
|
113
|
+
value,
|
|
114
|
+
expiresAt,
|
|
115
|
+
});
|
|
116
|
+
return value;
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
await repo.upsert({
|
|
124
|
+
key,
|
|
125
|
+
value,
|
|
126
|
+
expiresAt,
|
|
127
|
+
}, ['key']);
|
|
128
|
+
return value;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
this.logger?.error?.(`Failed to set key ${key}:`, error);
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async del(key) {
|
|
137
|
+
try {
|
|
138
|
+
const repo = this.getRepositoryForKey(key);
|
|
139
|
+
await repo.delete({ key });
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
this.logger?.error?.(`Failed to delete key ${key}:`, error);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
async exists(key) {
|
|
146
|
+
const value = await this.get(key);
|
|
147
|
+
return value !== null;
|
|
148
|
+
}
|
|
149
|
+
async incr(key, ttlSeconds) {
|
|
150
|
+
const repo = this.getRepositoryForKey(key);
|
|
151
|
+
return await repo.manager.transaction(async (transactionalEntityManager) => {
|
|
152
|
+
const record = await transactionalEntityManager.findOne(repo.target, {
|
|
153
|
+
where: { key },
|
|
154
|
+
lock: { mode: 'pessimistic_write' },
|
|
155
|
+
});
|
|
156
|
+
const now = new Date();
|
|
157
|
+
const isExpired = record && record.expiresAt && record.expiresAt < now;
|
|
158
|
+
if (record && !isExpired) {
|
|
159
|
+
const currentValue = parseInt(record.value, 10) || 0;
|
|
160
|
+
const newValue = currentValue + 1;
|
|
161
|
+
await transactionalEntityManager.update(repo.target, { key }, {
|
|
162
|
+
value: newValue.toString(),
|
|
163
|
+
});
|
|
164
|
+
return newValue;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
if (record) {
|
|
168
|
+
await transactionalEntityManager.delete(repo.target, { key });
|
|
169
|
+
}
|
|
170
|
+
const ttlToUse = ttlSeconds !== undefined ? ttlSeconds : 24 * 60 * 60;
|
|
171
|
+
const dbExpr = this.getDbNowPlusSecondsExpression(repo, ttlToUse);
|
|
172
|
+
await transactionalEntityManager
|
|
173
|
+
.createQueryBuilder()
|
|
174
|
+
.insert()
|
|
175
|
+
.into(repo.target)
|
|
176
|
+
.values([
|
|
177
|
+
{
|
|
178
|
+
key,
|
|
179
|
+
value: '1',
|
|
180
|
+
expiresAt: () => dbExpr,
|
|
181
|
+
},
|
|
182
|
+
])
|
|
183
|
+
.execute();
|
|
184
|
+
return 1;
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
async decr(key) {
|
|
189
|
+
const repo = this.getRepositoryForKey(key);
|
|
190
|
+
return await repo.manager.transaction(async (transactionalEntityManager) => {
|
|
191
|
+
const record = await transactionalEntityManager.findOne(repo.target, {
|
|
192
|
+
where: { key },
|
|
193
|
+
lock: { mode: 'pessimistic_write' },
|
|
194
|
+
});
|
|
195
|
+
if (record) {
|
|
196
|
+
const currentValue = parseInt(record.value, 10) || 0;
|
|
197
|
+
const newValue = Math.max(0, currentValue - 1);
|
|
198
|
+
await transactionalEntityManager.update(repo.target, { key }, {
|
|
199
|
+
value: newValue.toString(),
|
|
200
|
+
});
|
|
201
|
+
return newValue;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
const defaultExpiration = new Date(Date.now() + 24 * 60 * 60 * 1000);
|
|
205
|
+
await transactionalEntityManager.save(repo.target, {
|
|
206
|
+
key,
|
|
207
|
+
value: '0',
|
|
208
|
+
expiresAt: defaultExpiration,
|
|
209
|
+
});
|
|
210
|
+
return 0;
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
async expire(key, ttlSeconds) {
|
|
215
|
+
try {
|
|
216
|
+
const repo = this.getRepositoryForKey(key);
|
|
217
|
+
const dbExpr = this.getDbNowPlusSecondsExpression(repo, ttlSeconds);
|
|
218
|
+
const result = await repo
|
|
219
|
+
.createQueryBuilder()
|
|
220
|
+
.update(repo.target)
|
|
221
|
+
.set({ expiresAt: () => dbExpr })
|
|
222
|
+
.where({ key })
|
|
223
|
+
.execute();
|
|
224
|
+
if (result.affected === 0) {
|
|
225
|
+
this.logger?.warn?.(`Failed to set expiration for key ${key}: key does not exist`);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
this.logger?.debug?.(`Set expiration for key ${key}: ${ttlSeconds}s`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
233
|
+
this.logger?.error?.(`Failed to set expiration for key ${key}: ${errorMessage}`, { error, ttlSeconds });
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
getDbNowPlusSecondsExpression(repo, seconds) {
|
|
237
|
+
const dataSource = repo.manager.connection ?? repo.manager.dataSource;
|
|
238
|
+
const type = dataSource?.options?.type;
|
|
239
|
+
if (type === 'postgres') {
|
|
240
|
+
return `NOW() + INTERVAL '${seconds} seconds'`;
|
|
241
|
+
}
|
|
242
|
+
if (type === 'mysql' || type === 'mariadb') {
|
|
243
|
+
return `DATE_ADD(NOW(), INTERVAL ${seconds} SECOND)`;
|
|
244
|
+
}
|
|
245
|
+
if (type === 'sqlite' || type === 'better-sqlite3') {
|
|
246
|
+
return `DATETIME('now', '+${seconds} seconds')`;
|
|
247
|
+
}
|
|
248
|
+
return `NOW() + INTERVAL '${seconds} seconds'`;
|
|
249
|
+
}
|
|
250
|
+
async ttl(key) {
|
|
251
|
+
try {
|
|
252
|
+
const repo = this.getRepositoryForKey(key);
|
|
253
|
+
const record = await repo.findOne({
|
|
254
|
+
where: { key },
|
|
255
|
+
});
|
|
256
|
+
if (!record) {
|
|
257
|
+
return -1;
|
|
258
|
+
}
|
|
259
|
+
const expiresAt = record.expiresAt;
|
|
260
|
+
if (!expiresAt) {
|
|
261
|
+
return -2;
|
|
262
|
+
}
|
|
263
|
+
const ttlMs = expiresAt.getTime() - Date.now();
|
|
264
|
+
return Math.max(0, Math.ceil(ttlMs / 1000));
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
this.logger?.error?.(`Failed to get TTL for key ${key}:`, error);
|
|
268
|
+
return -1;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
async hset(key, field, value) {
|
|
272
|
+
try {
|
|
273
|
+
const hashKey = `hash:${key}`;
|
|
274
|
+
let hashData = {};
|
|
275
|
+
const existing = await this.get(hashKey);
|
|
276
|
+
if (existing) {
|
|
277
|
+
try {
|
|
278
|
+
hashData = JSON.parse(existing);
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
hashData[field] = value;
|
|
284
|
+
await this.set(hashKey, JSON.stringify(hashData));
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
this.logger?.error?.(`Failed to hset ${key} ${field}:`, error);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
async hget(key, field) {
|
|
291
|
+
try {
|
|
292
|
+
const hashKey = `hash:${key}`;
|
|
293
|
+
const hashDataStr = await this.get(hashKey);
|
|
294
|
+
if (!hashDataStr) {
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
try {
|
|
298
|
+
const hashData = JSON.parse(hashDataStr);
|
|
299
|
+
return hashData[field] || null;
|
|
300
|
+
}
|
|
301
|
+
catch {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
this.logger?.error?.(`Failed to hget ${key} ${field}:`, error);
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
async hgetall(key) {
|
|
311
|
+
try {
|
|
312
|
+
const hashKey = `hash:${key}`;
|
|
313
|
+
const hashDataStr = await this.get(hashKey);
|
|
314
|
+
if (!hashDataStr) {
|
|
315
|
+
return {};
|
|
316
|
+
}
|
|
317
|
+
try {
|
|
318
|
+
return JSON.parse(hashDataStr);
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
return {};
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
catch (error) {
|
|
325
|
+
this.logger?.error?.(`Failed to hgetall ${key}:`, error);
|
|
326
|
+
return {};
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
async hdel(key, ...fields) {
|
|
330
|
+
try {
|
|
331
|
+
const hashKey = `hash:${key}`;
|
|
332
|
+
const hashDataStr = await this.get(hashKey);
|
|
333
|
+
if (!hashDataStr) {
|
|
334
|
+
return 0;
|
|
335
|
+
}
|
|
336
|
+
let hashData;
|
|
337
|
+
try {
|
|
338
|
+
hashData = JSON.parse(hashDataStr);
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
return 0;
|
|
342
|
+
}
|
|
343
|
+
let deletedCount = 0;
|
|
344
|
+
for (const field of fields) {
|
|
345
|
+
if (field in hashData) {
|
|
346
|
+
delete hashData[field];
|
|
347
|
+
deletedCount++;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
if (deletedCount > 0) {
|
|
351
|
+
await this.set(hashKey, JSON.stringify(hashData));
|
|
352
|
+
}
|
|
353
|
+
return deletedCount;
|
|
354
|
+
}
|
|
355
|
+
catch (error) {
|
|
356
|
+
this.logger?.error?.(`Failed to hdel ${key}:`, error);
|
|
357
|
+
return 0;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
async lpush(key, value) {
|
|
361
|
+
try {
|
|
362
|
+
const listKey = `list:${key}`;
|
|
363
|
+
let listData = [];
|
|
364
|
+
const existing = await this.get(listKey);
|
|
365
|
+
if (existing) {
|
|
366
|
+
try {
|
|
367
|
+
listData = JSON.parse(existing);
|
|
368
|
+
if (!Array.isArray(listData)) {
|
|
369
|
+
listData = [];
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
catch {
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
listData.unshift(value);
|
|
376
|
+
await this.set(listKey, JSON.stringify(listData));
|
|
377
|
+
}
|
|
378
|
+
catch (error) {
|
|
379
|
+
this.logger?.error?.(`Failed to lpush ${key}:`, error);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
async lrange(key, start, stop) {
|
|
383
|
+
try {
|
|
384
|
+
const listKey = `list:${key}`;
|
|
385
|
+
const listDataStr = await this.get(listKey);
|
|
386
|
+
if (!listDataStr) {
|
|
387
|
+
return [];
|
|
388
|
+
}
|
|
389
|
+
let listData;
|
|
390
|
+
try {
|
|
391
|
+
listData = JSON.parse(listDataStr);
|
|
392
|
+
if (!Array.isArray(listData)) {
|
|
393
|
+
return [];
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
catch {
|
|
397
|
+
return [];
|
|
398
|
+
}
|
|
399
|
+
const len = listData.length;
|
|
400
|
+
if (start < 0)
|
|
401
|
+
start = Math.max(0, len + start);
|
|
402
|
+
if (stop < 0)
|
|
403
|
+
stop = len + stop;
|
|
404
|
+
if (stop >= len)
|
|
405
|
+
stop = len - 1;
|
|
406
|
+
if (start > stop || start >= len) {
|
|
407
|
+
return [];
|
|
408
|
+
}
|
|
409
|
+
return listData.slice(start, stop + 1);
|
|
410
|
+
}
|
|
411
|
+
catch (error) {
|
|
412
|
+
this.logger?.error?.(`Failed to lrange ${key}:`, error);
|
|
413
|
+
return [];
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
async llen(key) {
|
|
417
|
+
try {
|
|
418
|
+
const listKey = `list:${key}`;
|
|
419
|
+
const listDataStr = await this.get(listKey);
|
|
420
|
+
if (!listDataStr) {
|
|
421
|
+
return 0;
|
|
422
|
+
}
|
|
423
|
+
try {
|
|
424
|
+
const listData = JSON.parse(listDataStr);
|
|
425
|
+
return Array.isArray(listData) ? listData.length : 0;
|
|
426
|
+
}
|
|
427
|
+
catch {
|
|
428
|
+
return 0;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
catch (error) {
|
|
432
|
+
this.logger?.error?.(`Failed to llen ${key}:`, error);
|
|
433
|
+
return 0;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
async keys(pattern) {
|
|
437
|
+
try {
|
|
438
|
+
const likePattern = pattern
|
|
439
|
+
.replace(/\*/g, '%')
|
|
440
|
+
.replace(/\?/g, '_');
|
|
441
|
+
const now = new Date();
|
|
442
|
+
const rateLimitKeysPromise = this.rateLimitRepo.createQueryBuilder('record')
|
|
443
|
+
.where('record.key LIKE :pattern', { pattern: likePattern })
|
|
444
|
+
.andWhere('(record.expiresAt IS NULL OR record.expiresAt > :now)', { now })
|
|
445
|
+
.select('record.key')
|
|
446
|
+
.getRawMany();
|
|
447
|
+
const storageLockKeysPromise = this.storageLockRepo.createQueryBuilder('record')
|
|
448
|
+
.where('record.key LIKE :pattern', { pattern: likePattern })
|
|
449
|
+
.andWhere('(record.expiresAt IS NULL OR record.expiresAt > :now)', { now })
|
|
450
|
+
.select('record.key')
|
|
451
|
+
.getRawMany();
|
|
452
|
+
const [rateLimitRows, storageLockRows] = await Promise.all([rateLimitKeysPromise, storageLockKeysPromise]);
|
|
453
|
+
const keysSet = new Set();
|
|
454
|
+
for (const r of rateLimitRows)
|
|
455
|
+
keysSet.add(r.key);
|
|
456
|
+
for (const r of storageLockRows)
|
|
457
|
+
keysSet.add(r.key);
|
|
458
|
+
return Array.from(keysSet);
|
|
459
|
+
}
|
|
460
|
+
catch (error) {
|
|
461
|
+
this.logger?.error?.(`Failed to find keys with pattern ${pattern}:`, error);
|
|
462
|
+
return [];
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
async scan(cursor, pattern, count) {
|
|
466
|
+
try {
|
|
467
|
+
const keys = await this.keys(pattern);
|
|
468
|
+
const startIndex = cursor;
|
|
469
|
+
const endIndex = Math.min(startIndex + count, keys.length);
|
|
470
|
+
const resultKeys = keys.slice(startIndex, endIndex);
|
|
471
|
+
const nextCursor = endIndex < keys.length ? endIndex : 0;
|
|
472
|
+
return [nextCursor, resultKeys];
|
|
473
|
+
}
|
|
474
|
+
catch (error) {
|
|
475
|
+
this.logger?.error?.(`Failed to scan with pattern ${pattern}:`, error);
|
|
476
|
+
return [0, []];
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
async cleanup() {
|
|
480
|
+
try {
|
|
481
|
+
await this.rateLimitRepo.delete({
|
|
482
|
+
expiresAt: (0, typeorm_1.LessThan)(new Date()),
|
|
483
|
+
});
|
|
484
|
+
await this.storageLockRepo.delete({
|
|
485
|
+
expiresAt: (0, typeorm_1.LessThan)(new Date()),
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
catch (error) {
|
|
489
|
+
this.logger?.error?.('Failed to cleanup expired keys:', error);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
async disconnect() {
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
exports.DatabaseStorageAdapter = DatabaseStorageAdapter;
|
|
496
|
+
//# sourceMappingURL=database-storage.adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-storage.adapter.js","sourceRoot":"","sources":["../src/database-storage.adapter.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DatabaseStorageAdapter = void 0;
|
|
4
|
+
var database_storage_adapter_1 = require("./database-storage.adapter");
|
|
5
|
+
Object.defineProperty(exports, "DatabaseStorageAdapter", { enumerable: true, get: function () { return database_storage_adapter_1.DatabaseStorageAdapter; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAqBA,uEAAoE;AAA3D,kIAAA,sBAAsB,OAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nauth-toolkit/storage-database",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Database storage adapter for nauth-toolkit using TypeORM",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc -b",
|
|
9
|
+
"clean": "rm -rf dist *.tsbuildinfo",
|
|
10
|
+
"test": "jest",
|
|
11
|
+
"lint": "eslint src --ext .ts",
|
|
12
|
+
"lint:fix": "eslint src --ext .ts --fix",
|
|
13
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
14
|
+
"format:check": "prettier --check \"src/**/*.ts\""
|
|
15
|
+
},
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"@nauth-toolkit/core": "^0.1.3",
|
|
18
|
+
"typeorm": "^0.3.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/jest": "^29.5.0",
|
|
22
|
+
"@types/node": "^22.0.0",
|
|
23
|
+
"jest": "^29.7.0",
|
|
24
|
+
"ts-jest": "^29.2.0",
|
|
25
|
+
"typescript": "^5.5.0"
|
|
26
|
+
},
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=22.0.0"
|
|
29
|
+
},
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public",
|
|
32
|
+
"tag": "preview"
|
|
33
|
+
},
|
|
34
|
+
"license": "UNLICENSED",
|
|
35
|
+
"keywords": [
|
|
36
|
+
"nestjs",
|
|
37
|
+
"authentication",
|
|
38
|
+
"storage",
|
|
39
|
+
"database",
|
|
40
|
+
"typeorm"
|
|
41
|
+
],
|
|
42
|
+
"files": [
|
|
43
|
+
"dist",
|
|
44
|
+
"LICENSE",
|
|
45
|
+
"README.md"
|
|
46
|
+
]
|
|
47
|
+
}
|