jsgui3-server 0.0.138 → 0.0.140
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/AGENTS.md +87 -0
- package/README.md +12 -0
- package/docs/GUIDE_TO_AGENTIC_WORKFLOWS_BY_GROK.md +19 -0
- package/docs/advanced-usage-examples.md +1360 -0
- package/docs/agent-development-guide.md +386 -0
- package/docs/api-reference.md +916 -0
- package/docs/broken-functionality-tracker.md +285 -0
- package/docs/bundling-system-deep-dive.md +525 -0
- package/docs/cli-reference.md +393 -0
- package/docs/comprehensive-documentation.md +1403 -0
- package/docs/configuration-reference.md +808 -0
- package/docs/controls-development.md +859 -0
- package/docs/documentation-review/CURRENT_REVIEW.md +95 -0
- package/docs/function-publishers-json-apis.md +847 -0
- package/docs/getting-started-with-json.md +518 -0
- package/docs/minification-compression-sourcemaps-status.md +482 -0
- package/docs/minification-compression-sourcemaps-test-results.md +205 -0
- package/docs/publishers-guide.md +313 -0
- package/docs/resources-guide.md +615 -0
- package/docs/serve-helpers.md +406 -0
- package/docs/simple-server-api-design.md +13 -0
- package/docs/system-architecture.md +275 -0
- package/docs/troubleshooting.md +698 -0
- package/examples/json/README.md +115 -0
- package/examples/json/basic-api/README.md +345 -0
- package/examples/json/basic-api/server.js +199 -0
- package/examples/json/simple-api/README.md +125 -0
- package/examples/json/simple-api/diagnostic-report.json +73 -0
- package/examples/json/simple-api/diagnostic-test.js +433 -0
- package/examples/json/simple-api/server-debug.md +58 -0
- package/examples/json/simple-api/server.js +91 -0
- package/examples/json/simple-api/test.js +215 -0
- package/http/responders/static/Static_Route_HTTP_Responder.js +1 -2
- package/package.json +19 -8
- package/publishers/helpers/assigners/static-compressed-response-buffers/Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner.js +65 -12
- package/publishers/helpers/preparers/static/bundle/Static_Routes_Responses_Webpage_Bundle_Preparer.js +6 -1
- package/publishers/http-function-publisher.js +59 -38
- package/publishers/http-webpage-publisher.js +48 -1
- package/resources/processors/bundlers/js/esbuild/Advanced_JS_Bundler_Using_ESBuild.js +38 -146
- package/resources/processors/bundlers/js/esbuild/Core_JS_Non_Minifying_Bundler_Using_ESBuild.js +54 -5
- package/resources/processors/bundlers/js/esbuild/Core_JS_Single_File_Minifying_Bundler_Using_ESBuild.js +36 -4
- package/serve-factory.js +36 -9
- package/server.js +10 -4
- package/test-report.json +0 -0
- package/tests/README.md +250 -0
- package/tests/assigners.test.js +316 -0
- package/tests/bundlers.test.js +329 -0
- package/tests/configuration-validation.test.js +530 -0
- package/tests/content-analysis.test.js +641 -0
- package/tests/end-to-end.test.js +496 -0
- package/tests/error-handling.test.js +746 -0
- package/tests/performance.test.js +653 -0
- package/tests/publishers.test.js +395 -0
- package/tests/temp_invalid.js +7 -0
- package/tests/temp_invalid_utf8.js +1 -0
- package/tests/temp_malformed.js +10 -0
- package/tests/test-runner.js +261 -0
|
@@ -0,0 +1,615 @@
|
|
|
1
|
+
# Resources Guide
|
|
2
|
+
|
|
3
|
+
## When to Read
|
|
4
|
+
|
|
5
|
+
This document explains the resource system in JSGUI3 Server. Read this when:
|
|
6
|
+
- You need to understand how data and functionality are abstracted in the server
|
|
7
|
+
- You're creating custom resources for new data sources
|
|
8
|
+
- You want to extend the server with new capabilities
|
|
9
|
+
- You're working with resource pools and lifecycle management
|
|
10
|
+
- You need to understand server-side data access patterns
|
|
11
|
+
|
|
12
|
+
**Note:** For general server usage, see [README.md](../README.md). For system architecture, see [docs/system-architecture.md](docs/system-architecture.md).
|
|
13
|
+
|
|
14
|
+
## Overview
|
|
15
|
+
|
|
16
|
+
Resources are JSGUI3 Server's abstraction layer for accessing data, functionality, and external systems. They provide a unified interface for different types of data sources while handling lifecycle management, error handling, and performance optimization.
|
|
17
|
+
|
|
18
|
+
## Resource Types
|
|
19
|
+
|
|
20
|
+
### Server_Resource_Pool
|
|
21
|
+
|
|
22
|
+
**Purpose:** Manages collections of resources with access control and lifecycle management.
|
|
23
|
+
|
|
24
|
+
**Key Features:**
|
|
25
|
+
- Resource registration and discovery
|
|
26
|
+
- Access control through permission systems
|
|
27
|
+
- Lifecycle management (start/stop/cleanup)
|
|
28
|
+
- Resource dependency resolution
|
|
29
|
+
|
|
30
|
+
**Usage:**
|
|
31
|
+
```javascript
|
|
32
|
+
const pool = new Server_Resource_Pool({
|
|
33
|
+
access: {
|
|
34
|
+
full: ['admin'],
|
|
35
|
+
read: ['user']
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
pool.add(myResource);
|
|
40
|
+
pool.start((err) => {
|
|
41
|
+
// Pool is ready
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Website_Resource
|
|
46
|
+
|
|
47
|
+
**Purpose:** Wraps website objects for integration with the server's resource system.
|
|
48
|
+
|
|
49
|
+
**Key Features:**
|
|
50
|
+
- Website object encapsulation
|
|
51
|
+
- HTTP request processing
|
|
52
|
+
- Resource pool integration
|
|
53
|
+
- Lifecycle management
|
|
54
|
+
|
|
55
|
+
### File_System_Resource
|
|
56
|
+
|
|
57
|
+
**Purpose:** Provides secure, abstracted access to the file system.
|
|
58
|
+
|
|
59
|
+
**Key Features:**
|
|
60
|
+
- Path validation and security
|
|
61
|
+
- File reading/writing operations
|
|
62
|
+
- Directory traversal protection
|
|
63
|
+
- Asynchronous file operations
|
|
64
|
+
|
|
65
|
+
### Data_Resource
|
|
66
|
+
|
|
67
|
+
**Purpose:** Generic data storage and retrieval abstraction.
|
|
68
|
+
|
|
69
|
+
**Key Features:**
|
|
70
|
+
- Multiple storage backends support
|
|
71
|
+
- Query interfaces
|
|
72
|
+
- Data validation and transformation
|
|
73
|
+
- Connection pooling
|
|
74
|
+
|
|
75
|
+
### Local_Server_Info_Resource
|
|
76
|
+
|
|
77
|
+
**Purpose:** Provides information about the server environment and network interfaces.
|
|
78
|
+
|
|
79
|
+
**Key Features:**
|
|
80
|
+
- Network interface detection
|
|
81
|
+
- Server configuration access
|
|
82
|
+
- Environment information
|
|
83
|
+
- Dynamic updates
|
|
84
|
+
|
|
85
|
+
## Resource Architecture
|
|
86
|
+
|
|
87
|
+
### Base Resource Class
|
|
88
|
+
|
|
89
|
+
All resources extend the base `Resource` class:
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
const jsgui = require('jsgui3-html');
|
|
93
|
+
const Resource = jsgui.Resource;
|
|
94
|
+
|
|
95
|
+
class Custom_Resource extends Resource {
|
|
96
|
+
constructor(spec = {}) {
|
|
97
|
+
super(spec);
|
|
98
|
+
this.__type_name = 'custom_resource';
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
start(callback) {
|
|
102
|
+
// Resource initialization
|
|
103
|
+
callback(null);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
stop(callback) {
|
|
107
|
+
// Resource cleanup
|
|
108
|
+
callback(null);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Lifecycle Management
|
|
114
|
+
|
|
115
|
+
Resources follow a consistent lifecycle:
|
|
116
|
+
|
|
117
|
+
1. **Construction**: Resource is instantiated with configuration
|
|
118
|
+
2. **Registration**: Added to resource pool
|
|
119
|
+
3. **Start**: Resource becomes active and available
|
|
120
|
+
4. **Usage**: Resource handles requests and operations
|
|
121
|
+
5. **Stop**: Resource is deactivated
|
|
122
|
+
6. **Cleanup**: Resources are released
|
|
123
|
+
|
|
124
|
+
### Configuration Patterns
|
|
125
|
+
|
|
126
|
+
Resources use specification objects for configuration:
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
const resource = new Custom_Resource({
|
|
130
|
+
name: 'My Resource',
|
|
131
|
+
access: ['read', 'write'],
|
|
132
|
+
config: {
|
|
133
|
+
// Resource-specific configuration
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Creating Custom Resources
|
|
139
|
+
|
|
140
|
+
### Basic Resource Structure
|
|
141
|
+
|
|
142
|
+
```javascript
|
|
143
|
+
class Database_Resource extends Resource {
|
|
144
|
+
constructor(spec = {}) {
|
|
145
|
+
super(spec);
|
|
146
|
+
this.connection_string = spec.connection_string;
|
|
147
|
+
this.pool_size = spec.pool_size || 10;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
start(callback) {
|
|
151
|
+
// Establish database connection
|
|
152
|
+
this.connect((err) => {
|
|
153
|
+
if (err) return callback(err);
|
|
154
|
+
console.log('Database connected');
|
|
155
|
+
callback(null);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
query(sql, params, callback) {
|
|
160
|
+
// Execute database query
|
|
161
|
+
this.connection.query(sql, params, callback);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
stop(callback) {
|
|
165
|
+
// Close database connection
|
|
166
|
+
this.connection.end(() => {
|
|
167
|
+
console.log('Database disconnected');
|
|
168
|
+
callback(null);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Integration with Server
|
|
175
|
+
|
|
176
|
+
```javascript
|
|
177
|
+
// Add to resource pool
|
|
178
|
+
server.resource_pool.add(databaseResource);
|
|
179
|
+
|
|
180
|
+
// Access from other components
|
|
181
|
+
const db = server.resource_pool.get_resource('Database_Resource');
|
|
182
|
+
db.query('SELECT * FROM users', [], (err, results) => {
|
|
183
|
+
// Handle results
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Resource Communication Patterns
|
|
188
|
+
|
|
189
|
+
### Synchronous Access
|
|
190
|
+
|
|
191
|
+
```javascript
|
|
192
|
+
const resource = pool.get_resource('My_Resource');
|
|
193
|
+
const result = resource.get_data();
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Asynchronous Access
|
|
197
|
+
|
|
198
|
+
```javascript
|
|
199
|
+
resource.get_data_async((err, data) => {
|
|
200
|
+
if (err) {
|
|
201
|
+
// Handle error
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
// Process data
|
|
205
|
+
});
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Promise-Based Access
|
|
209
|
+
|
|
210
|
+
```javascript
|
|
211
|
+
resource.get_data_promise()
|
|
212
|
+
.then(data => {
|
|
213
|
+
// Process data
|
|
214
|
+
})
|
|
215
|
+
.catch(err => {
|
|
216
|
+
// Handle error
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Event-Driven Access
|
|
221
|
+
|
|
222
|
+
```javascript
|
|
223
|
+
resource.on('data_updated', (new_data) => {
|
|
224
|
+
// Handle data update
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
resource.on('error', (error) => {
|
|
228
|
+
// Handle resource error
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Error Handling
|
|
233
|
+
|
|
234
|
+
### Resource Errors
|
|
235
|
+
|
|
236
|
+
Resources should handle and propagate errors appropriately:
|
|
237
|
+
|
|
238
|
+
```javascript
|
|
239
|
+
class File_Resource extends Resource {
|
|
240
|
+
read_file(path, callback) {
|
|
241
|
+
fs.readFile(path, 'utf8', (err, data) => {
|
|
242
|
+
if (err) {
|
|
243
|
+
if (err.code === 'ENOENT') {
|
|
244
|
+
return callback(new Error(`File not found: ${path}`));
|
|
245
|
+
}
|
|
246
|
+
return callback(new Error(`Read error: ${err.message}`));
|
|
247
|
+
}
|
|
248
|
+
callback(null, data);
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Error Propagation
|
|
255
|
+
|
|
256
|
+
```javascript
|
|
257
|
+
// In publisher or other component
|
|
258
|
+
const resource = pool.get_resource('File_Resource');
|
|
259
|
+
resource.read_file('/path/to/file', (err, data) => {
|
|
260
|
+
if (err) {
|
|
261
|
+
// Log error
|
|
262
|
+
console.error('Resource error:', err);
|
|
263
|
+
// Send appropriate HTTP response
|
|
264
|
+
response.statusCode = 500;
|
|
265
|
+
response.end('Internal Server Error');
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
// Process data
|
|
269
|
+
});
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Performance Optimization
|
|
273
|
+
|
|
274
|
+
### Connection Pooling
|
|
275
|
+
|
|
276
|
+
```javascript
|
|
277
|
+
class Pooled_Resource extends Resource {
|
|
278
|
+
constructor(spec = {}) {
|
|
279
|
+
super(spec);
|
|
280
|
+
this.pool = [];
|
|
281
|
+
this.max_connections = spec.max_connections || 10;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
get_connection(callback) {
|
|
285
|
+
if (this.pool.length > 0) {
|
|
286
|
+
return callback(null, this.pool.pop());
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (this.active_connections < this.max_connections) {
|
|
290
|
+
this.create_connection(callback);
|
|
291
|
+
} else {
|
|
292
|
+
// Queue request or return error
|
|
293
|
+
callback(new Error('Connection pool exhausted'));
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
release_connection(connection) {
|
|
298
|
+
if (this.pool.length < this.max_connections) {
|
|
299
|
+
this.pool.push(connection);
|
|
300
|
+
} else {
|
|
301
|
+
connection.close();
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Caching
|
|
308
|
+
|
|
309
|
+
```javascript
|
|
310
|
+
class Cached_Resource extends Resource {
|
|
311
|
+
constructor(spec = {}) {
|
|
312
|
+
super(spec);
|
|
313
|
+
this.cache = new Map();
|
|
314
|
+
this.cache_ttl = spec.cache_ttl || 300000; // 5 minutes
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
get_cached(key, fetch_function, callback) {
|
|
318
|
+
const cached = this.cache.get(key);
|
|
319
|
+
if (cached && Date.now() - cached.timestamp < this.cache_ttl) {
|
|
320
|
+
return callback(null, cached.data);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
fetch_function((err, data) => {
|
|
324
|
+
if (err) return callback(err);
|
|
325
|
+
|
|
326
|
+
this.cache.set(key, {
|
|
327
|
+
data: data,
|
|
328
|
+
timestamp: Date.now()
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
callback(null, data);
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Lazy Loading
|
|
338
|
+
|
|
339
|
+
```javascript
|
|
340
|
+
class Lazy_Resource extends Resource {
|
|
341
|
+
constructor(spec = {}) {
|
|
342
|
+
super(spec);
|
|
343
|
+
this._initialized = false;
|
|
344
|
+
this._initializing = false;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
ensure_initialized(callback) {
|
|
348
|
+
if (this._initialized) {
|
|
349
|
+
return callback(null);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (this._initializing) {
|
|
353
|
+
// Wait for ongoing initialization
|
|
354
|
+
this.once('initialized', () => callback(null));
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
this._initializing = true;
|
|
359
|
+
this.initialize((err) => {
|
|
360
|
+
this._initializing = false;
|
|
361
|
+
if (err) return callback(err);
|
|
362
|
+
|
|
363
|
+
this._initialized = true;
|
|
364
|
+
this.emit('initialized');
|
|
365
|
+
callback(null);
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## Security Considerations
|
|
372
|
+
|
|
373
|
+
### Access Control
|
|
374
|
+
|
|
375
|
+
```javascript
|
|
376
|
+
class Secure_Resource extends Resource {
|
|
377
|
+
constructor(spec = {}) {
|
|
378
|
+
super(spec);
|
|
379
|
+
this.required_permissions = spec.required_permissions || [];
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
check_access(user_permissions, operation) {
|
|
383
|
+
return this.required_permissions.every(perm =>
|
|
384
|
+
user_permissions.includes(perm)
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
perform_operation(user, operation, ...args) {
|
|
389
|
+
if (!this.check_access(user.permissions, operation)) {
|
|
390
|
+
throw new Error('Access denied');
|
|
391
|
+
}
|
|
392
|
+
// Perform operation
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### Input Validation
|
|
398
|
+
|
|
399
|
+
```javascript
|
|
400
|
+
class Validated_Resource extends Resource {
|
|
401
|
+
validate_input(input, schema) {
|
|
402
|
+
// Implement validation logic
|
|
403
|
+
if (!input || typeof input !== 'object') {
|
|
404
|
+
throw new Error('Invalid input: must be an object');
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
for (const [key, validator] of Object.entries(schema)) {
|
|
408
|
+
if (!validator(input[key])) {
|
|
409
|
+
throw new Error(`Invalid ${key}: ${input[key]}`);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
process_data(input, callback) {
|
|
415
|
+
try {
|
|
416
|
+
this.validate_input(input, this.input_schema);
|
|
417
|
+
// Process validated input
|
|
418
|
+
} catch (err) {
|
|
419
|
+
callback(err);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
## Testing Resources
|
|
426
|
+
|
|
427
|
+
### Unit Testing
|
|
428
|
+
|
|
429
|
+
```javascript
|
|
430
|
+
const Resource_Test = require('./test_helpers');
|
|
431
|
+
|
|
432
|
+
describe('Custom_Resource', () => {
|
|
433
|
+
let resource;
|
|
434
|
+
|
|
435
|
+
beforeEach(() => {
|
|
436
|
+
resource = new Custom_Resource({
|
|
437
|
+
name: 'Test Resource'
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
it('should initialize correctly', (done) => {
|
|
442
|
+
resource.start((err) => {
|
|
443
|
+
expect(err).toBeNull();
|
|
444
|
+
expect(resource.initialized).toBe(true);
|
|
445
|
+
done();
|
|
446
|
+
});
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
it('should handle errors gracefully', (done) => {
|
|
450
|
+
resource.invalid_operation((err) => {
|
|
451
|
+
expect(err).toBeDefined();
|
|
452
|
+
expect(err.message).toContain('error');
|
|
453
|
+
done();
|
|
454
|
+
});
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### Integration Testing
|
|
460
|
+
|
|
461
|
+
```javascript
|
|
462
|
+
describe('Resource Integration', () => {
|
|
463
|
+
let server;
|
|
464
|
+
let pool;
|
|
465
|
+
|
|
466
|
+
beforeAll((done) => {
|
|
467
|
+
server = new Server();
|
|
468
|
+
pool = server.resource_pool;
|
|
469
|
+
pool.start(done);
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
it('should integrate with server', () => {
|
|
473
|
+
const resource = pool.get_resource('My_Resource');
|
|
474
|
+
expect(resource).toBeDefined();
|
|
475
|
+
expect(resource.active).toBe(true);
|
|
476
|
+
});
|
|
477
|
+
});
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
## Best Practices
|
|
481
|
+
|
|
482
|
+
### Resource Design
|
|
483
|
+
- Keep resources focused on single responsibilities
|
|
484
|
+
- Use consistent configuration patterns
|
|
485
|
+
- Provide clear error messages
|
|
486
|
+
- Document resource capabilities and limitations
|
|
487
|
+
|
|
488
|
+
### Performance
|
|
489
|
+
- Implement connection pooling for expensive resources
|
|
490
|
+
- Use caching for frequently accessed data
|
|
491
|
+
- Minimize synchronous operations
|
|
492
|
+
- Monitor resource usage and performance
|
|
493
|
+
|
|
494
|
+
### Maintainability
|
|
495
|
+
- Follow existing code patterns and conventions
|
|
496
|
+
- Add comprehensive tests for all resources
|
|
497
|
+
- Document configuration options and usage
|
|
498
|
+
- Provide migration guides for changes
|
|
499
|
+
|
|
500
|
+
### Security
|
|
501
|
+
- Implement proper access controls
|
|
502
|
+
- Validate all inputs and outputs
|
|
503
|
+
- Handle sensitive data appropriately
|
|
504
|
+
- Log security-relevant events
|
|
505
|
+
|
|
506
|
+
## Common Patterns
|
|
507
|
+
|
|
508
|
+
### Resource Composition
|
|
509
|
+
|
|
510
|
+
```javascript
|
|
511
|
+
class Composite_Resource extends Resource {
|
|
512
|
+
constructor(spec = {}) {
|
|
513
|
+
super(spec);
|
|
514
|
+
this.sub_resources = spec.resources || [];
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
start(callback) {
|
|
518
|
+
async.parallel(
|
|
519
|
+
this.sub_resources.map(r => r.start.bind(r)),
|
|
520
|
+
callback
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
get_combined_data(callback) {
|
|
525
|
+
async.parallel(
|
|
526
|
+
this.sub_resources.map(r => r.get_data.bind(r)),
|
|
527
|
+
(err, results) => {
|
|
528
|
+
if (err) return callback(err);
|
|
529
|
+
callback(null, this.combine_results(results));
|
|
530
|
+
}
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### Resource Monitoring
|
|
537
|
+
|
|
538
|
+
```javascript
|
|
539
|
+
class Monitored_Resource extends Resource {
|
|
540
|
+
constructor(spec = {}) {
|
|
541
|
+
super(spec);
|
|
542
|
+
this.metrics = {
|
|
543
|
+
requests: 0,
|
|
544
|
+
errors: 0,
|
|
545
|
+
avg_response_time: 0
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
track_operation(operation, start_time) {
|
|
550
|
+
this.metrics.requests++;
|
|
551
|
+
const duration = Date.now() - start_time;
|
|
552
|
+
this.metrics.avg_response_time =
|
|
553
|
+
(this.metrics.avg_response_time + duration) / 2;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
get_metrics() {
|
|
557
|
+
return { ...this.metrics };
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
## Troubleshooting
|
|
563
|
+
|
|
564
|
+
### Common Issues
|
|
565
|
+
- Resource not starting due to configuration errors
|
|
566
|
+
- Connection failures in pooled resources
|
|
567
|
+
- Memory leaks in long-running resources
|
|
568
|
+
- Race conditions in asynchronous operations
|
|
569
|
+
|
|
570
|
+
### Debug Mode
|
|
571
|
+
|
|
572
|
+
```javascript
|
|
573
|
+
const resource = new Custom_Resource({
|
|
574
|
+
debug: true,
|
|
575
|
+
log_level: 'verbose'
|
|
576
|
+
});
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
### Logging
|
|
580
|
+
|
|
581
|
+
Resources should provide comprehensive logging:
|
|
582
|
+
|
|
583
|
+
```javascript
|
|
584
|
+
class Logged_Resource extends Resource {
|
|
585
|
+
log(level, message, data = {}) {
|
|
586
|
+
const timestamp = new Date().toISOString();
|
|
587
|
+
console.log(`[${timestamp}] ${level.toUpperCase()}: ${message}`, data);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
start(callback) {
|
|
591
|
+
this.log('info', 'Starting resource', { name: this.name });
|
|
592
|
+
// ... initialization logic
|
|
593
|
+
this.log('info', 'Resource started successfully');
|
|
594
|
+
callback(null);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
## Future Enhancements
|
|
600
|
+
|
|
601
|
+
### Planned Features
|
|
602
|
+
- Advanced monitoring and metrics
|
|
603
|
+
- Automatic scaling and load balancing
|
|
604
|
+
- Enhanced security features
|
|
605
|
+
- Resource discovery and service meshes
|
|
606
|
+
|
|
607
|
+
### Extension Points
|
|
608
|
+
- Plugin system for custom resources
|
|
609
|
+
- Resource composition frameworks
|
|
610
|
+
- Advanced caching strategies
|
|
611
|
+
- Distributed resource management
|
|
612
|
+
|
|
613
|
+
---
|
|
614
|
+
|
|
615
|
+
This guide provides the foundation for understanding and extending the resource system. For specific resource implementations, refer to their individual source files in the `resources/` directory.
|