owservable 1.6.3 → 1.7.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/README.md +441 -160
- package/lib/auth/i.connection.manager.d.ts +1 -1
- package/lib/enums/store.type.enum.js.map +1 -0
- package/lib/functions/action/add.action.cronjobs.d.ts +1 -1
- package/lib/functions/action/add.action.cronjobs.js +22 -16
- package/lib/functions/action/add.action.cronjobs.js.map +1 -1
- package/lib/functions/action/add.action.watchers.d.ts +1 -1
- package/lib/functions/action/add.action.watchers.js +22 -13
- package/lib/functions/action/add.action.watchers.js.map +1 -1
- package/lib/functions/action/add.action.workers.d.ts +1 -1
- package/lib/functions/action/add.action.workers.js +22 -13
- package/lib/functions/action/add.action.workers.js.map +1 -1
- package/lib/functions/execute/execute.cronjob.d.ts +1 -1
- package/lib/functions/execute/execute.processes.in.folder.d.ts +1 -1
- package/lib/functions/execute/execute.processes.in.folder.js +2 -2
- package/lib/functions/execute/execute.processes.in.folder.js.map +1 -1
- package/lib/functions/execute/execute.watcher.d.ts +1 -1
- package/lib/functions/execute/execute.worker.d.ts +1 -1
- package/lib/owservable.d.ts +9 -9
- package/lib/owservable.js +1 -1
- package/lib/owservable.js.map +1 -1
- package/lib/store/a.store.d.ts +3 -2
- package/lib/store/a.store.js +2 -2
- package/lib/store/a.store.js.map +1 -1
- package/lib/store/collection.store.js +1 -2
- package/lib/store/collection.store.js.map +1 -1
- package/lib/store/count.store.js +1 -2
- package/lib/store/count.store.js.map +1 -1
- package/lib/store/document.store.js +1 -2
- package/lib/store/document.store.js.map +1 -1
- package/lib/store/factories/store.factory.d.ts +1 -1
- package/lib/types/connection.manager.refresh.type.js.map +1 -0
- package/lib/types/cronjob.type.js.map +1 -0
- package/lib/types/store.scope.type.js.map +1 -0
- package/lib/types/store.subscription.config.type.js.map +1 -0
- package/lib/types/store.subscription.update.type.js.map +1 -0
- package/lib/types/subscription.methods.type.js.map +1 -0
- package/lib/types/watcher.type.js.map +1 -0
- package/lib/types/worker.type.js.map +1 -0
- package/package.json +17 -19
- package/lib/_enums/store.type.enum.js.map +0 -1
- package/lib/_types/connection.manager.refresh.type.js.map +0 -1
- package/lib/_types/cronjob.type.js.map +0 -1
- package/lib/_types/store.scope.type.js.map +0 -1
- package/lib/_types/store.subscription.config.type.js.map +0 -1
- package/lib/_types/store.subscription.update.type.js.map +0 -1
- package/lib/_types/subscription.methods.type.js.map +0 -1
- package/lib/_types/watcher.type.js.map +0 -1
- package/lib/_types/worker.type.js.map +0 -1
- /package/lib/{_enums → enums}/store.type.enum.d.ts +0 -0
- /package/lib/{_enums → enums}/store.type.enum.js +0 -0
- /package/lib/{_types → types}/connection.manager.refresh.type.d.ts +0 -0
- /package/lib/{_types → types}/connection.manager.refresh.type.js +0 -0
- /package/lib/{_types → types}/cronjob.type.d.ts +0 -0
- /package/lib/{_types → types}/cronjob.type.js +0 -0
- /package/lib/{_types → types}/store.scope.type.d.ts +0 -0
- /package/lib/{_types → types}/store.scope.type.js +0 -0
- /package/lib/{_types → types}/store.subscription.config.type.d.ts +0 -0
- /package/lib/{_types → types}/store.subscription.config.type.js +0 -0
- /package/lib/{_types → types}/store.subscription.update.type.d.ts +0 -0
- /package/lib/{_types → types}/store.subscription.update.type.js +0 -0
- /package/lib/{_types → types}/subscription.methods.type.d.ts +0 -0
- /package/lib/{_types → types}/subscription.methods.type.js +0 -0
- /package/lib/{_types → types}/watcher.type.d.ts +0 -0
- /package/lib/{_types → types}/watcher.type.js +0 -0
- /package/lib/{_types → types}/worker.type.d.ts +0 -0
- /package/lib/{_types → types}/worker.type.js +0 -0
package/README.md
CHANGED
|
@@ -1,169 +1,450 @@
|
|
|
1
1
|

|
|
2
2
|
|
|
3
|
-
# Owservable
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
##
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
3
|
+
# Owservable
|
|
4
|
+
|
|
5
|
+
A reactive backend library for Node.js applications that provides real-time MongoDB change streams, reactive data stores, and automated task scheduling. Built with RxJS and TypeScript.
|
|
6
|
+
|
|
7
|
+
**Owservable is a replacement for [Reactive Stack JS](https://github.com/reactive-stack-js).**
|
|
8
|
+
|
|
9
|
+
## 🚀 Features
|
|
10
|
+
|
|
11
|
+
- **Real-time MongoDB Integration**: MongoDB change streams with reactive observables
|
|
12
|
+
- **Reactive Data Stores**: Count, Document, and Collection stores with automatic updates
|
|
13
|
+
- **WebSocket Client Management**: Built-in client connection and subscription handling
|
|
14
|
+
- **Task Scheduling**: Automated cronjobs, watchers, and workers
|
|
15
|
+
- **Action Pattern**: Structured business logic with multiple execution contexts
|
|
16
|
+
- **Data Middleware**: Transform and filter data based on user permissions
|
|
17
|
+
- **Type Safety**: Full TypeScript support with comprehensive type definitions
|
|
18
|
+
|
|
19
|
+
## 📦 Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install owservable
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
or
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
yarn add owservable
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
or
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pnpm add owservable
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 🏗️ Requirements
|
|
38
|
+
|
|
39
|
+
- **Node.js**: >= 20
|
|
40
|
+
- **MongoDB**: >= 3.6 (Replica Set required for change streams)
|
|
41
|
+
- **TypeScript**: Recommended for full type safety
|
|
42
|
+
|
|
43
|
+
## 🔧 MongoDB Setup
|
|
44
|
+
|
|
45
|
+
Owservable requires MongoDB to be running as a Replica Set to enable change streams:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Start MongoDB as a single-node replica set
|
|
49
|
+
mongod --replSet rs0
|
|
50
|
+
|
|
51
|
+
# Initialize the replica set
|
|
52
|
+
mongo --eval "rs.initiate()"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
For more details, see: [MongoDB Change Streams on localhost with Node.js](http://stojadinovic.net/2020/07/05/mongodb-change-streams-on-localhost-with-nodejs/)
|
|
56
|
+
|
|
57
|
+
## 🚀 Quick Start
|
|
58
|
+
|
|
59
|
+
### 1. Basic Server Setup
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import {
|
|
63
|
+
OwservableClient,
|
|
64
|
+
MongoDBConnector,
|
|
65
|
+
processModels,
|
|
66
|
+
IConnectionManager
|
|
67
|
+
} from 'owservable';
|
|
68
|
+
|
|
69
|
+
// Initialize MongoDB connection
|
|
70
|
+
const mongoConnector = new MongoDBConnector();
|
|
71
|
+
await mongoConnector.connect('mongodb://localhost:27017/myapp');
|
|
72
|
+
|
|
73
|
+
// Process your Mongoose models
|
|
74
|
+
await processModels('./models');
|
|
75
|
+
|
|
76
|
+
// Implement connection manager
|
|
77
|
+
class MyConnectionManager implements IConnectionManager {
|
|
78
|
+
async connected(jwt: string): Promise<void> {
|
|
79
|
+
// Handle client connection
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async disconnected(): Promise<void> {
|
|
83
|
+
// Handle client disconnection
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async checkSession(): Promise<any> {
|
|
87
|
+
// Handle session validation
|
|
88
|
+
return { refresh_in: 300000 };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
ping(ms: number): void {
|
|
92
|
+
// Handle ping updates
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
location(path: string): void {
|
|
96
|
+
// Handle location updates
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
get user(): any {
|
|
100
|
+
// Return current user
|
|
101
|
+
return this.currentUser;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Create owservable client
|
|
106
|
+
const connectionManager = new MyConnectionManager();
|
|
107
|
+
const client = new OwservableClient(connectionManager);
|
|
108
|
+
|
|
109
|
+
// Handle client messages
|
|
110
|
+
client.subscribe({
|
|
111
|
+
next: (message) => {
|
|
112
|
+
// Forward to WebSocket clients
|
|
113
|
+
websocket.send(JSON.stringify(message));
|
|
114
|
+
},
|
|
115
|
+
error: (error) => console.error('Client error:', error)
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### 2. WebSocket Integration
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { WebSocketServer } from 'ws';
|
|
123
|
+
|
|
124
|
+
const wss = new WebSocketServer({ port: 8080 });
|
|
125
|
+
|
|
126
|
+
wss.on('connection', (ws) => {
|
|
127
|
+
const client = new OwservableClient(connectionManager);
|
|
128
|
+
|
|
129
|
+
// Subscribe to client updates
|
|
130
|
+
client.subscribe({
|
|
131
|
+
next: (message) => ws.send(JSON.stringify(message)),
|
|
132
|
+
error: (error) => console.error('Error:', error)
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// Handle incoming messages
|
|
136
|
+
ws.on('message', async (data) => {
|
|
137
|
+
const message = JSON.parse(data.toString());
|
|
138
|
+
await client.consume(message);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// Handle disconnect
|
|
142
|
+
ws.on('close', () => {
|
|
143
|
+
client.disconnected();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Start ping
|
|
147
|
+
client.ping();
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### 3. Reactive Data Stores
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
import { storeFactory, EStoreType } from 'owservable';
|
|
155
|
+
|
|
156
|
+
// Count store - returns only document count
|
|
157
|
+
const countStore = storeFactory(EStoreType.COUNT, 'users', 'user-count');
|
|
158
|
+
countStore.config = {
|
|
159
|
+
query: { active: true },
|
|
160
|
+
fields: {}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// Collection store - returns array of documents
|
|
164
|
+
const collectionStore = storeFactory(EStoreType.COLLECTION, 'users', 'user-list');
|
|
165
|
+
collectionStore.config = {
|
|
166
|
+
query: { active: true },
|
|
167
|
+
fields: { name: 1, email: 1 },
|
|
168
|
+
sort: { name: 1 },
|
|
169
|
+
page: 1,
|
|
170
|
+
pageSize: 10
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// Document store - returns single document
|
|
174
|
+
const documentStore = storeFactory(EStoreType.DOCUMENT, 'users', 'user-profile');
|
|
175
|
+
documentStore.config = {
|
|
176
|
+
query: { _id: 'user123' },
|
|
177
|
+
fields: { name: 1, email: 1, profile: 1 }
|
|
178
|
+
};
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### 4. Task Scheduling
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
import {
|
|
185
|
+
initiateCronjobs,
|
|
186
|
+
initiateWatchers,
|
|
187
|
+
initiateWorkers
|
|
188
|
+
} from 'owservable';
|
|
189
|
+
|
|
190
|
+
// Initialize cronjobs
|
|
191
|
+
await initiateCronjobs('./cronjobs');
|
|
192
|
+
|
|
193
|
+
// Initialize file watchers
|
|
194
|
+
await initiateWatchers('./watchers');
|
|
195
|
+
|
|
196
|
+
// Initialize background workers
|
|
197
|
+
await initiateWorkers('./workers');
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### 5. Data Middleware
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import { DataMiddlewareMap } from 'owservable';
|
|
204
|
+
|
|
205
|
+
// Register middleware for collection
|
|
206
|
+
DataMiddlewareMap.set('users', async (payload, user) => {
|
|
207
|
+
// Filter sensitive data based on user permissions
|
|
208
|
+
if (!user.isAdmin) {
|
|
209
|
+
payload.data = payload.data.map(doc => ({
|
|
210
|
+
...doc,
|
|
211
|
+
email: '***@***.***' // Hide emails for non-admins
|
|
212
|
+
}));
|
|
213
|
+
}
|
|
214
|
+
return payload;
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## 📚 Core Components
|
|
39
219
|
|
|
40
220
|
### OwservableClient
|
|
41
221
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
###
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
###
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
222
|
+
The main client class that manages WebSocket connections and subscriptions:
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
const client = new OwservableClient(connectionManager);
|
|
226
|
+
|
|
227
|
+
// Handle different message types
|
|
228
|
+
await client.consume({
|
|
229
|
+
type: 'subscribe',
|
|
230
|
+
target: 'user-list',
|
|
231
|
+
scope: 'collection',
|
|
232
|
+
observe: 'users',
|
|
233
|
+
config: {
|
|
234
|
+
query: { active: true },
|
|
235
|
+
fields: { name: 1, email: 1 }
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Store Types
|
|
241
|
+
|
|
242
|
+
#### CollectionStore
|
|
243
|
+
Returns arrays of documents with real-time updates:
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
const store = storeFactory(EStoreType.COLLECTION, 'posts', 'post-list');
|
|
247
|
+
store.config = {
|
|
248
|
+
query: { published: true },
|
|
249
|
+
fields: { title: 1, content: 1, author: 1 },
|
|
250
|
+
sort: { createdAt: -1 },
|
|
251
|
+
populate: ['author'],
|
|
252
|
+
page: 1,
|
|
253
|
+
pageSize: 20,
|
|
254
|
+
incremental: true // Enable incremental updates
|
|
255
|
+
};
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### CountStore
|
|
259
|
+
Returns document counts with real-time updates:
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
const store = storeFactory(EStoreType.COUNT, 'users', 'user-count');
|
|
263
|
+
store.config = {
|
|
264
|
+
query: { active: true }
|
|
265
|
+
};
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
#### DocumentStore
|
|
269
|
+
Returns single documents with real-time updates:
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
const store = storeFactory(EStoreType.DOCUMENT, 'users', 'current-user');
|
|
273
|
+
store.config = {
|
|
274
|
+
query: { _id: userId },
|
|
275
|
+
fields: { name: 1, email: 1, preferences: 1 }
|
|
276
|
+
};
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### MongoDB Integration
|
|
280
|
+
|
|
281
|
+
#### Observable Models
|
|
282
|
+
Monitor MongoDB collections for changes:
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
import { observableModel } from 'owservable';
|
|
286
|
+
import UserModel from './models/User';
|
|
287
|
+
|
|
288
|
+
const userObservable = observableModel(UserModel);
|
|
289
|
+
userObservable.subscribe({
|
|
290
|
+
next: (change) => {
|
|
291
|
+
console.log('User collection changed:', change);
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
#### Observable Database
|
|
297
|
+
Monitor entire database for changes:
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
import { observableDatabase } from 'owservable';
|
|
301
|
+
|
|
302
|
+
const dbObservable = observableDatabase();
|
|
303
|
+
dbObservable.subscribe({
|
|
304
|
+
next: (change) => {
|
|
305
|
+
console.log('Database changed:', change);
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Action Pattern
|
|
311
|
+
|
|
312
|
+
Create structured business logic with the action pattern:
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
import { Action, ActionInterface } from 'owservable';
|
|
316
|
+
|
|
317
|
+
class SendEmailAction extends Action implements ActionInterface {
|
|
318
|
+
protected _description = 'Send email notification';
|
|
319
|
+
|
|
320
|
+
async handle(to: string, subject: string, body: string): Promise<void> {
|
|
321
|
+
// Email sending logic
|
|
322
|
+
console.log(`Sending email to ${to}: ${subject}`);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
description(): string {
|
|
326
|
+
return this._description;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Use in cronjobs, workers, or watchers
|
|
331
|
+
const emailAction = new SendEmailAction();
|
|
332
|
+
await emailAction.handle('user@example.com', 'Welcome!', 'Hello World');
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## 🔧 Configuration
|
|
336
|
+
|
|
337
|
+
### Environment Variables
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
# MongoDB connection
|
|
341
|
+
MONGODB_URI=mongodb://localhost:27017/myapp
|
|
342
|
+
|
|
343
|
+
# WebSocket server
|
|
344
|
+
WS_PORT=8080
|
|
345
|
+
|
|
346
|
+
# JWT settings
|
|
347
|
+
JWT_SECRET=your-secret-key
|
|
348
|
+
JWT_EXPIRATION=24h
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### TypeScript Configuration
|
|
352
|
+
|
|
353
|
+
```json
|
|
354
|
+
{
|
|
355
|
+
"compilerOptions": {
|
|
356
|
+
"target": "ES2020",
|
|
357
|
+
"module": "commonjs",
|
|
358
|
+
"lib": ["ES2020"],
|
|
359
|
+
"strict": true,
|
|
360
|
+
"esModuleInterop": true,
|
|
361
|
+
"skipLibCheck": true,
|
|
362
|
+
"forceConsistentCasingInFileNames": true,
|
|
363
|
+
"experimentalDecorators": true,
|
|
364
|
+
"emitDecoratorMetadata": true
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
## 📖 Advanced Usage
|
|
370
|
+
|
|
371
|
+
### Custom Store Implementation
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
import { AStore, EStoreType } from 'owservable';
|
|
375
|
+
|
|
376
|
+
class CustomStore extends AStore {
|
|
377
|
+
constructor(model: Model<any>, target: string) {
|
|
378
|
+
super(model, target);
|
|
379
|
+
this._type = EStoreType.COLLECTION;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
protected async load(change: any): Promise<void> {
|
|
383
|
+
// Custom loading logic
|
|
384
|
+
const data = await this.customQuery();
|
|
385
|
+
this.emitMany(Date.now(), this._subscriptionId, { data });
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Performance Optimization
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
// Use incremental updates for large collections
|
|
394
|
+
store.config = {
|
|
395
|
+
incremental: true,
|
|
396
|
+
page: 1,
|
|
397
|
+
pageSize: 50
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
// Optimize queries with indexes
|
|
401
|
+
await addIndexToAttributes(model, ['field1', 'field2']);
|
|
402
|
+
|
|
403
|
+
// Use field projection
|
|
404
|
+
store.config = {
|
|
405
|
+
fields: {
|
|
406
|
+
name: 1,
|
|
407
|
+
email: 1,
|
|
408
|
+
_id: 0 // Exclude _id
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
## 🧪 Testing
|
|
414
|
+
|
|
415
|
+
```bash
|
|
416
|
+
npm test
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
## 📖 Documentation
|
|
420
|
+
|
|
421
|
+
- **Main Website**: [owservable.github.io](https://owservable.github.io/)
|
|
422
|
+
- **TypeDoc Documentation**: [owservable.github.io/owservable/docs/](https://owservable.github.io/owservable/docs/)
|
|
423
|
+
- **Test Coverage**: [owservable.github.io/owservable/coverage/](https://owservable.github.io/owservable/coverage/)
|
|
424
|
+
- **Udemy Course**: [Reactive Stack Course](https://www.udemy.com/course/reactive-stack/)
|
|
425
|
+
|
|
426
|
+
## 🔗 Related Projects
|
|
427
|
+
|
|
428
|
+
- [@owservable/actions](https://github.com/owservable/actions) - Action pattern implementation
|
|
429
|
+
- [@owservable/folders](https://github.com/owservable/folders) - File system utilities
|
|
430
|
+
- [@owservable/fastify-auto-routes](https://github.com/owservable/fastify-auto-routes) - Fastify auto routing
|
|
431
|
+
|
|
432
|
+
## 🛣️ Roadmap
|
|
433
|
+
|
|
434
|
+
- [ ] Web Server abstraction
|
|
435
|
+
- [ ] Database abstraction
|
|
436
|
+
- [ ] Client-side datastore abstraction
|
|
437
|
+
- [ ] Large Data handling
|
|
438
|
+
- [ ] Server-Side Events
|
|
439
|
+
- [ ] Redis integration
|
|
440
|
+
- [ ] GraphQL subscriptions
|
|
441
|
+
- [ ] Microservices support
|
|
442
|
+
|
|
443
|
+
## 📄 License
|
|
163
444
|
|
|
164
445
|
Licensed under [The Unlicense](./LICENSE).
|
|
165
446
|
|
|
166
|
-
##
|
|
447
|
+
## 🤝 Contributors
|
|
167
448
|
|
|
168
449
|
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
|
169
450
|
<!-- prettier-ignore-start -->
|
|
@@ -196,6 +477,6 @@ This project follows the [all-contributors](https://github.com/all-contributors/
|
|
|
196
477
|
|
|
197
478
|
Contributions of any kind welcome!
|
|
198
479
|
|
|
199
|
-
##
|
|
480
|
+
## 📊 UML Diagram
|
|
200
481
|
|
|
201
|
-
Checkout the [UML diagram](https://raw.githubusercontent.com/owservable/owservable/main/uml.png).
|
|
482
|
+
Checkout the [UML diagram](https://raw.githubusercontent.com/owservable/owservable/main/uml.png) for a visual overview of the architecture.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.type.enum.js","sourceRoot":"","sources":["../../src/enums/store.type.enum.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,IAAK,UAIJ;AAJD,WAAK,UAAU;IACd,mDAAQ,CAAA;IACR,uDAAU,CAAA;IACV,6CAAK,CAAA;AACN,CAAC,EAJI,UAAU,KAAV,UAAU,QAId;AAED,kBAAe,UAAU,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export default function addActionCronjobs(root: string, folderName: string): void
|
|
1
|
+
export default function addActionCronjobs(root: string, folderName: string): Promise<void>;
|
|
@@ -1,26 +1,32 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
2
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
12
|
exports.default = addActionCronjobs;
|
|
4
13
|
const lodash_1 = require("lodash");
|
|
5
14
|
const folders_1 = require("@owservable/folders");
|
|
6
15
|
const execute_cronjob_1 = require("../execute/execute.cronjob");
|
|
7
16
|
function addActionCronjobs(root, folderName) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
schedule: action.schedule(),
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if ((0, lodash_1.isFunction)(action.asCronjobInit))
|
|
21
|
-
(0, lodash_1.set)(job, 'init', action.asCronjobInit());
|
|
22
|
-
(0, execute_cronjob_1.default)(job);
|
|
17
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
18
|
+
const actionPaths = yield (0, folders_1.listSubfoldersFilesByFolderName)(root, folderName);
|
|
19
|
+
for (const actionPath of actionPaths) {
|
|
20
|
+
console.log('[@owservable] -> Initializing cronjob action', actionPath);
|
|
21
|
+
const ActionClass = require(actionPath).default;
|
|
22
|
+
const action = new ActionClass();
|
|
23
|
+
if ((0, lodash_1.isFunction)(action.asCronjob)) {
|
|
24
|
+
const job = Object.assign(Object.assign({ schedule: action.schedule() }, (action.asCronjobInit && { init: action.asCronjobInit })), { job: action.asCronjob });
|
|
25
|
+
if ((0, lodash_1.isFunction)(action.asCronjobInit))
|
|
26
|
+
(0, lodash_1.set)(job, 'init', action.asCronjobInit());
|
|
27
|
+
(0, execute_cronjob_1.default)(job);
|
|
28
|
+
}
|
|
23
29
|
}
|
|
24
|
-
}
|
|
30
|
+
});
|
|
25
31
|
}
|
|
26
32
|
//# sourceMappingURL=add.action.cronjobs.js.map
|