@brightchain/node-express-suite 0.25.0 → 0.26.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 +354 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,11 +1,360 @@
|
|
|
1
|
-
# brightchain
|
|
1
|
+
# @brightchain/node-express-suite
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
|
|
5
|
+
The BrightStack parallel to [`@digitaldefiance/node-express-suite`](https://github.com/Digital-Defiance/express-suite). Where the upstream library provides a complete MERN (Mongo, Express, React, Node) backend framework, this library provides the same application architecture backed by BrightChain's content-addressable block store instead of MongoDB - enabling the BrightStack (BrightDB, Express, React, Node) development path.
|
|
6
|
+
|
|
7
|
+
Part of [BrightChain](https://github.com/Digital-Defiance/BrightChain)
|
|
8
|
+
|
|
9
|
+
## What is node-express-suite?
|
|
10
|
+
|
|
11
|
+
`@digitaldefiance/node-express-suite` is an opinionated, secure, extensible Node.js/Express service framework built on Digital Defiance cryptography libraries. It provides complete backend infrastructure including:
|
|
12
|
+
|
|
13
|
+
- JWT authentication with mnemonic and ECIES crypto auth
|
|
14
|
+
- Role-based access control (RBAC)
|
|
15
|
+
- Dynamic model registry for extensible document schemas
|
|
16
|
+
- Plugin-based database architecture (`IDatabasePlugin`)
|
|
17
|
+
- Service container with base service classes
|
|
18
|
+
- Multi-language i18n support
|
|
19
|
+
- Email token workflows (verification, password reset, recovery)
|
|
20
|
+
- ECIES encryption/decryption and PBKDF2 key derivation
|
|
21
|
+
- Decorator-based controller API with automatic OpenAPI generation
|
|
22
|
+
- Transaction management, session adapters, and middleware pipeline
|
|
23
|
+
- Runtime configuration registry
|
|
24
|
+
|
|
25
|
+
All of this is built around MongoDB/Mongoose as the storage layer.
|
|
26
|
+
|
|
27
|
+
## What does this library do?
|
|
28
|
+
|
|
29
|
+
`@brightchain/node-express-suite` replaces the MongoDB/Mongoose storage layer with BrightChain's content-addressable block store while preserving the upstream's application architecture, plugin system, service patterns, and API contracts. Every Mongoose-specific component has a BrightDB parallel:
|
|
30
|
+
|
|
31
|
+
| Upstream (MERN) | BrightStack | Role |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| `MongoBaseService` | `BrightDbBaseService` | Base class for database-aware services |
|
|
34
|
+
| `MongooseCollection` | `BrightDbCollection` | Collection adapter implementing `ICollection` |
|
|
35
|
+
| `MongooseDocumentStore` | `BlockDocumentStore` | Document store with Mongoose-compatible query API |
|
|
36
|
+
| `MongooseSessionAdapter` | `BrightChainSessionAdapter` | JWT session management |
|
|
37
|
+
| `MongoDatabasePlugin` | `BrightDbDatabasePlugin` | `IDatabasePlugin` implementation for app lifecycle |
|
|
38
|
+
| `MongoAuthenticationProvider` | `BrightDbAuthenticationProvider` | User lookup and JWT verification |
|
|
39
|
+
| `ModelRegistry` | `BrightDbModelRegistry` | Singleton collection registration |
|
|
40
|
+
| `TransactionManager` | `BrightDbTransactionManager` | Transaction lifecycle with retry/timeout |
|
|
41
|
+
| `BaseEnvironment` + `.mongo` | `BrightDbEnvironment` | Environment config with block store settings |
|
|
42
|
+
| `IMongoApplication` | `IBrightDbApplication` | Typed application interface |
|
|
43
|
+
|
|
44
|
+
This means code written against the upstream's service patterns, plugin architecture, and controller decorators works with BrightDB by swapping the database layer - the Express infrastructure, auth, i18n, RBAC, and middleware all carry over from upstream.
|
|
45
|
+
|
|
46
|
+
## What BrightStack adds beyond the upstream
|
|
47
|
+
|
|
48
|
+
Beyond the 1:1 Mongoose replacements, this library adds capabilities unique to BrightChain:
|
|
49
|
+
|
|
50
|
+
- Content-addressable storage where document identity is derived from content (SHA3-512)
|
|
51
|
+
- Quorum-based document encryption via `QuorumService` - documents are sealed so that multiple members must cooperate to decrypt
|
|
52
|
+
- Per-document access control with `hasAccess()`, `findAccessibleBy()`, and `findByIdDecrypted()`
|
|
53
|
+
- Multiple storage backends: local disk, in-memory (dev/test), Azure Blob Storage, and Amazon S3
|
|
54
|
+
- Block-level deduplication - identical documents are stored once
|
|
55
|
+
|
|
56
|
+
## Architecture
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
@digitaldefiance/node-express-suite (upstream MERN framework)
|
|
60
|
+
|
|
|
61
|
+
| extends
|
|
62
|
+
v
|
|
63
|
+
@brightchain/node-express-suite (this library - BrightStack database layer)
|
|
64
|
+
|
|
|
65
|
+
| extends
|
|
66
|
+
v
|
|
67
|
+
@brightchain/brightchain-api-lib (domain-specific BrightChain API)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The upstream provides the Express application skeleton, plugin system, auth, i18n, decorators, and middleware. This library slots in the BrightDB database layer. Domain-specific code (member stores, energy accounts, etc.) lives in `brightchain-api-lib` which extends this library further.
|
|
71
|
+
|
|
72
|
+
## Installation
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
yarn add @brightchain/node-express-suite
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Peer Dependencies
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"@digitaldefiance/branded-interface": "^0.0.5",
|
|
83
|
+
"@digitaldefiance/node-ecies-lib": "^4.20.0",
|
|
84
|
+
"@digitaldefiance/node-express-suite": "^4.20.1",
|
|
85
|
+
"@brightchain/brightchain-lib": "^0.25.0",
|
|
86
|
+
"@brightchain/db": "^0.25.0"
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Quick Start
|
|
91
|
+
|
|
92
|
+
### Basic Application Setup
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import {
|
|
96
|
+
BrightDbApplication,
|
|
97
|
+
BrightDbEnvironment,
|
|
98
|
+
configureBrightDbApp,
|
|
99
|
+
} from '@brightchain/node-express-suite';
|
|
100
|
+
|
|
101
|
+
// Environment reads from .env / process.env
|
|
102
|
+
const environment = new BrightDbEnvironment();
|
|
103
|
+
|
|
104
|
+
// Create application (extends upstream Application)
|
|
105
|
+
const app = new BrightDbApplication(environment);
|
|
106
|
+
|
|
107
|
+
// Register the BrightDB database plugin
|
|
108
|
+
const { plugin } = configureBrightDbApp(app, environment);
|
|
109
|
+
|
|
110
|
+
// Connect - no URI needed, uses environment-based block store config
|
|
111
|
+
await plugin.connect();
|
|
112
|
+
|
|
113
|
+
// Start the Express server
|
|
114
|
+
await app.start();
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Database Initialization
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
import { brightchainDatabaseInit } from '@brightchain/node-express-suite';
|
|
121
|
+
|
|
122
|
+
const result = await brightchainDatabaseInit(environment, {
|
|
123
|
+
modelRegistrations: async (db, blockStore) => {
|
|
124
|
+
// Register domain-specific collections here
|
|
125
|
+
const users = db.collection('users');
|
|
126
|
+
const projects = db.collection('projects');
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
if (result.success) {
|
|
131
|
+
const { blockStore, db } = result.backend;
|
|
132
|
+
console.log('BrightDB connected');
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Core Components
|
|
137
|
+
|
|
138
|
+
### BrightDbEnvironment
|
|
139
|
+
|
|
140
|
+
Extends the upstream `BaseEnvironment` with BrightDB-specific configuration parsed from environment variables:
|
|
141
|
+
|
|
142
|
+
| Variable | Type | Default | Description |
|
|
143
|
+
|---|---|---|---|
|
|
144
|
+
| `BRIGHTCHAIN_BLOCKSTORE_PATH` | `string` | - | Path to the on-disk block store |
|
|
145
|
+
| `BRIGHTCHAIN_BLOCKSIZE_BYTES` | `string` | `Medium` | Comma-separated block sizes |
|
|
146
|
+
| `BRIGHTCHAIN_BLOCKSTORE_TYPE` | `string` | `disk` | Storage backend: `disk`, `azure-blob`, `s3` |
|
|
147
|
+
| `USE_MEMORY_DOCSTORE` | `boolean` | `false` | Use in-memory store (no persistence) |
|
|
148
|
+
| `DEV_DATABASE` | `string` | - | Pool name for ephemeral dev database |
|
|
149
|
+
| `MEMBER_POOL_NAME` | `string` | `BrightChain` | Member pool name |
|
|
150
|
+
|
|
151
|
+
Azure and S3 backends require additional variables - see the `BrightDbEnvironment` class for details.
|
|
152
|
+
|
|
153
|
+
### BlockDocumentStore
|
|
154
|
+
|
|
155
|
+
Content-addressable document store backed by BrightChain blocks. Implements a Mongoose-compatible query API so existing code migrates with minimal changes.
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
import { BlockDocumentStore } from '@brightchain/node-express-suite';
|
|
159
|
+
|
|
160
|
+
const store = new BlockDocumentStore(blockStore);
|
|
161
|
+
const users = store.collection('users');
|
|
162
|
+
|
|
163
|
+
// CRUD operations - same API as Mongoose
|
|
164
|
+
await users.create({ name: 'Alice', email: 'alice@example.com' });
|
|
165
|
+
const user = await users.findOne({ name: 'Alice' }).exec();
|
|
166
|
+
await users.updateOne({ name: 'Alice' }, { email: 'alice@new.com' });
|
|
167
|
+
await users.deleteOne({ name: 'Alice' });
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Encrypted Documents (Quorum Sealing)
|
|
171
|
+
|
|
172
|
+
Documents can be encrypted using BrightChain's quorum-based sealing, where multiple members must cooperate to decrypt:
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
const store = new BlockDocumentStore(blockStore, quorumService);
|
|
176
|
+
const secrets = store.encryptedCollection('secrets');
|
|
177
|
+
|
|
178
|
+
// Create an encrypted document
|
|
179
|
+
await secrets.create(
|
|
180
|
+
{ data: 'sensitive payload' },
|
|
181
|
+
{
|
|
182
|
+
encrypt: true,
|
|
183
|
+
agent: sealingMember,
|
|
184
|
+
memberIds: [member1Id, member2Id, member3Id],
|
|
185
|
+
sharesRequired: 2,
|
|
186
|
+
},
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
// Check access
|
|
190
|
+
const hasAccess = await secrets.hasAccess(docId, memberHexId);
|
|
191
|
+
|
|
192
|
+
// Decrypt with sufficient member keys
|
|
193
|
+
const decrypted = await secrets.findByIdDecrypted(docId, {
|
|
194
|
+
membersWithPrivateKey: [member1, member2],
|
|
195
|
+
});
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### BrightDbDatabasePlugin
|
|
199
|
+
|
|
200
|
+
Implements the upstream `IDatabasePlugin` interface for the express-suite plugin architecture:
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import {
|
|
204
|
+
BrightDbDatabasePlugin,
|
|
205
|
+
BrightDbEnvironment,
|
|
206
|
+
} from '@brightchain/node-express-suite';
|
|
207
|
+
|
|
208
|
+
const plugin = new BrightDbDatabasePlugin(environment);
|
|
209
|
+
await plugin.connect(); // No URI - uses environment config
|
|
210
|
+
|
|
211
|
+
// Access the underlying stores
|
|
212
|
+
const blockStore = plugin.blockStore;
|
|
213
|
+
const db = plugin.brightDb;
|
|
214
|
+
|
|
215
|
+
// Cleanup
|
|
216
|
+
await plugin.disconnect();
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### BrightDbModelRegistry
|
|
220
|
+
|
|
221
|
+
Singleton registry for BrightDB collections, parallel to upstream's `ModelRegistry` for Mongoose models:
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
import {
|
|
225
|
+
BrightDbModelRegistry,
|
|
226
|
+
BrightDbCollection,
|
|
227
|
+
} from '@brightchain/node-express-suite';
|
|
228
|
+
|
|
229
|
+
// Register a collection
|
|
230
|
+
BrightDbModelRegistry.instance.register({
|
|
231
|
+
collectionName: 'organizations',
|
|
232
|
+
collection: new BrightDbCollection(db.collection('organizations')),
|
|
233
|
+
schema: orgSchema,
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Retrieve anywhere in the app
|
|
237
|
+
const orgReg = BrightDbModelRegistry.instance.get('organizations');
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### BrightDbTransactionManager
|
|
241
|
+
|
|
242
|
+
Session-based transaction support with retry logic and timeouts:
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
import { BrightDbTransactionManager } from '@brightchain/node-express-suite';
|
|
246
|
+
|
|
247
|
+
const txMgr = new BrightDbTransactionManager(db, true);
|
|
248
|
+
|
|
249
|
+
await txMgr.execute(
|
|
250
|
+
async (session) => {
|
|
251
|
+
// Operations within a transaction
|
|
252
|
+
await users.create({ name: 'Bob' });
|
|
253
|
+
await accounts.create({ owner: 'Bob', balance: 0 });
|
|
254
|
+
},
|
|
255
|
+
{ maxRetries: 2, timeoutMs: 5000 },
|
|
256
|
+
);
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### BrightChainSessionAdapter
|
|
260
|
+
|
|
261
|
+
JWT session management backed by BrightDB:
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
import { BrightChainSessionAdapter } from '@brightchain/node-express-suite';
|
|
265
|
+
|
|
266
|
+
const sessions = new BrightChainSessionAdapter(db);
|
|
267
|
+
|
|
268
|
+
// Create a session (token is SHA-256 hashed for storage)
|
|
269
|
+
const sessionId = await sessions.createSession(memberId, jwtToken, ttlMs);
|
|
270
|
+
|
|
271
|
+
// Validate a token
|
|
272
|
+
const session = await sessions.validateToken(jwtToken);
|
|
273
|
+
|
|
274
|
+
// Cleanup expired sessions
|
|
275
|
+
const removed = await sessions.cleanExpired();
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### BrightDbAuthenticationProvider
|
|
279
|
+
|
|
280
|
+
Generic authentication provider with JWT verification and user lookup from BrightDB:
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
import { BrightDbAuthenticationProvider } from '@brightchain/node-express-suite';
|
|
284
|
+
|
|
285
|
+
const auth = new BrightDbAuthenticationProvider(db, jwtSecret);
|
|
286
|
+
|
|
287
|
+
const user = await auth.findUserById(userId);
|
|
288
|
+
const tokenUser = await auth.verifyToken(jwtToken);
|
|
289
|
+
const requestUser = await auth.buildRequestUserDTO(userId);
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### BrightDbBaseService
|
|
293
|
+
|
|
294
|
+
Base class for services that need typed access to the BrightDB application:
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
import { BrightDbBaseService } from '@brightchain/node-express-suite';
|
|
298
|
+
|
|
299
|
+
class ProjectService extends BrightDbBaseService {
|
|
300
|
+
async getProjects() {
|
|
301
|
+
const col = this.application.getModel('projects');
|
|
302
|
+
return col.find({}).exec();
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## Upstream Re-exports
|
|
308
|
+
|
|
309
|
+
For convenience, this library re-exports key upstream symbols so consumers don't need to depend on `@digitaldefiance/node-express-suite` directly:
|
|
310
|
+
|
|
311
|
+
- `Application`, `AppRouter`, `createExpressConstants` (classes/functions)
|
|
312
|
+
- `IApplication`, `IConstants`, `IAuthenticationProvider`, `IDatabasePlugin`, `IEnvironment` (interfaces)
|
|
313
|
+
|
|
314
|
+
It also re-exports from `@brightchain/db` (`BrightDb`, `Collection`) and `@brightchain/brightchain-lib` (`BlockSize`, `BlockStoreType`, `IBlockStore`).
|
|
315
|
+
|
|
316
|
+
## Storage Backends
|
|
317
|
+
|
|
318
|
+
| Backend | Env Config | Description |
|
|
319
|
+
|---|---|---|
|
|
320
|
+
| Disk | `BRIGHTCHAIN_BLOCKSTORE_TYPE=disk` | Persistent local storage at `BRIGHTCHAIN_BLOCKSTORE_PATH` |
|
|
321
|
+
| Memory | `DEV_DATABASE=<pool-name>` | Ephemeral in-memory store for development/testing |
|
|
322
|
+
| Azure Blob | `BRIGHTCHAIN_BLOCKSTORE_TYPE=azure-blob` | Azure Blob Storage (requires `AZURE_STORAGE_*` vars) |
|
|
323
|
+
| S3 | `BRIGHTCHAIN_BLOCKSTORE_TYPE=s3` | Amazon S3 (requires `AWS_S3_BUCKET_NAME` and credentials) |
|
|
324
|
+
|
|
325
|
+
## MERN to BrightStack Migration
|
|
326
|
+
|
|
327
|
+
See [MIGRATION.md](./MIGRATION.md) for a step-by-step guide to migrate from `@digitaldefiance/node-express-suite` (Mongoose/MongoDB) to `@brightchain/node-express-suite` (BrightDB).
|
|
328
|
+
|
|
329
|
+
## Testing
|
|
330
|
+
|
|
331
|
+
A test utility is included for creating in-memory BrightDB instances:
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
import { createTestApp } from '@brightchain/node-express-suite';
|
|
335
|
+
|
|
336
|
+
const { plugin, environment, teardown } = await createTestApp();
|
|
337
|
+
|
|
338
|
+
// Use plugin.brightDb for test operations
|
|
339
|
+
const db = plugin.brightDb;
|
|
340
|
+
const users = db.collection('users');
|
|
341
|
+
|
|
342
|
+
// Cleanup
|
|
343
|
+
await teardown();
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Running Tests
|
|
347
|
+
|
|
348
|
+
```bash
|
|
349
|
+
yarn nx test brightchain-node-express-suite
|
|
350
|
+
```
|
|
4
351
|
|
|
5
352
|
## Building
|
|
6
353
|
|
|
7
|
-
|
|
354
|
+
```bash
|
|
355
|
+
yarn nx build brightchain-node-express-suite
|
|
356
|
+
```
|
|
8
357
|
|
|
9
|
-
##
|
|
358
|
+
## License
|
|
10
359
|
|
|
11
|
-
|
|
360
|
+
MIT
|