qtools-library-dot-d 1.0.7 → 1.0.9
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 +19 -25
- package/libDotD_Working_Example/README.md +234 -0
- package/libDotD_Working_Example/demoModules_DotD/demo1.js +46 -0
- package/libDotD_Working_Example/demoModules_DotD/demo2.js +48 -0
- package/libDotD_Working_Example/index.js +133 -0
- package/libDotD_Working_Example/node_modules/.package-lock.json +29 -0
- package/libDotD_Working_Example/node_modules/qtools-asynchronous-pipe-plus/README.md +213 -0
- package/libDotD_Working_Example/node_modules/qtools-asynchronous-pipe-plus/package.json +20 -0
- package/libDotD_Working_Example/node_modules/qtools-asynchronous-pipe-plus/qtools-asynchronous-pipe-plus.js +278 -0
- package/libDotD_Working_Example/node_modules/qtools-asynchronous-pipe-plus/test.js +79 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/README.md +110 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-clone/package.json +11 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-clone/qtools-clone.js +103 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-clone/test.js +78 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-get-by-property/package.json +11 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-get-by-property/qtools-get-by-property.js +73 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-get-by-property/test.js +129 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-includes-regex/package.json +11 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-includes-regex/qtools-includes-regex.js +54 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-includes-regex/test.js +76 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-log-output/package.json +11 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-log-output/qtools-log-output.js +114 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-log-output/test.js +130 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-map-properties/package.json +11 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-map-properties/qtools-map-properties.js +99 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-map-properties/test.js +118 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-merge/package.json +11 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-merge/qtools-merge.js +147 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-merge/test.js +214 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-new-method-template/package.json +11 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-new-method-template/qtools-new-method-template.js +70 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-new-method-template/test.js +66 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-number-iterator/package.json +11 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-number-iterator/qtools-number-iterator.js +137 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-number-iterator/test.js +68 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-number-keys-to-array/package.json +11 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-number-keys-to-array/qtools-number-keys-to-array.js +131 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-number-keys-to-array/test.js +181 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-object-sure-path/package.json +11 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-object-sure-path/qtools-object-sure-path.js +204 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-object-sure-path/test.js +345 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-pass-through/package.json +11 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-pass-through/qtools-pass-through.js +58 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-pass-through/test.js +66 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-pop/package.json +11 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-pop/qtools-pop.js +175 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-pop/test.js +118 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-print-debug/package.json +11 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-print-debug/qtools-print-debug.js +352 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-print-debug/test.js +77 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-select-properties/package.json +11 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-select-properties/qtools-select-properties.js +132 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-select-properties/test.js +156 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-template-replace/README.md +3 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-template-replace/package.json +11 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-template-replace/qtools-template-replace.js +106 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-template-replace/test.js +168 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-to-key-value-array/package.json +11 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-to-key-value-array/qtools-to-key-value-array.js +83 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-to-key-value-array/test.js +68 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-to-string/package.json +11 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-to-string/qtools-to-string.js +84 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-to-string/test.js +63 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/package.json +37 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/qtFunctionalDemo.js +297 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/qtools-functional-library.js +271 -0
- package/libDotD_Working_Example/node_modules/qtools-functional-library/test.js +47 -0
- package/libDotD_Working_Example/node_modules/qtools-library-dot-d/README.md +208 -0
- package/libDotD_Working_Example/node_modules/qtools-library-dot-d/package.json +15 -0
- package/libDotD_Working_Example/node_modules/qtools-library-dot-d/qtools-library-dot-d.js +239 -0
- package/libDotD_Working_Example/package-lock.json +37 -0
- package/libDotD_Working_Example/package.json +23 -0
- package/package.json +1 -1
- package/qtools-library-dot-d.js +2 -2
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ The "dotD" naming convention (short for "dot-D") refers to directories that cont
|
|
|
15
15
|
- `accessPoints.d/` - Directory containing data access modules
|
|
16
16
|
- `mappers.d/` - Directory containing data mapping modules
|
|
17
17
|
|
|
18
|
-
Each `.js` file in a dotD directory becomes a method on the library object, with the filename determining the method name.
|
|
18
|
+
Each module, `.js` file or directory with package.json, in a dotD directory becomes a method on the library object, with the filename determining the method name.
|
|
19
19
|
|
|
20
20
|
## Why Use Dynamic dotD Libraries?
|
|
21
21
|
|
|
@@ -30,10 +30,10 @@ const module2 = require('./modules/module2');
|
|
|
30
30
|
const module3 = require('./modules/module3');
|
|
31
31
|
|
|
32
32
|
// dotD approach - automatic discovery
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
// All modules in modules.d/ are now available as
|
|
33
|
+
const myLibrary = qtLibDotD({ libraryName: 'myLibrary' }); //libraryName is used as a label in reports
|
|
34
|
+
myLibrary.setLibraryPath('./modules.d');
|
|
35
|
+
myLibrary.loadModules();
|
|
36
|
+
// All modules in modules.d/ are now available as myLibrary.moduleName()
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
### 2. **Plugin Architecture**
|
|
@@ -42,12 +42,12 @@ Create extensible applications where new functionality can be added by simply dr
|
|
|
42
42
|
|
|
43
43
|
```javascript
|
|
44
44
|
// Add new functionality by creating a new file
|
|
45
|
-
// modules.d/newFeature.js ->
|
|
45
|
+
// modules.d/newFeature.js -> myLibrary.newFeature()
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
### 3. **Shared Resources**
|
|
49
49
|
|
|
50
|
-
Pass common resources (configuration, database connections, utilities) to all modules through `passThroughParameters`.
|
|
50
|
+
Pass common resources (configuration, database connections, utilities) to all modules through `passThroughParameters`. These are given, by that name, to the module (along with the 'dotD', the library object) when it is instantiated during the loadModules() process.
|
|
51
51
|
|
|
52
52
|
```javascript
|
|
53
53
|
const passThroughParameters = {
|
|
@@ -56,7 +56,7 @@ const passThroughParameters = {
|
|
|
56
56
|
logger: xLog,
|
|
57
57
|
utilities: commonUtils
|
|
58
58
|
};
|
|
59
|
-
|
|
59
|
+
myLibrary.loadModules({ passThroughParameters });
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
### 4. **Clean Separation of Concerns**
|
|
@@ -111,13 +111,13 @@ Modules can be loaded synchronously or asynchronously, and the library can be se
|
|
|
111
111
|
|
|
112
112
|
```javascript
|
|
113
113
|
const qtLibDotD = require('qtools-library-dot-d');
|
|
114
|
-
const
|
|
114
|
+
const myLibrary = qtLibDotD({ libraryName: 'myLibrary' });
|
|
115
115
|
```
|
|
116
116
|
|
|
117
117
|
### 2. **Module Directory Setup**
|
|
118
118
|
|
|
119
119
|
```javascript
|
|
120
|
-
|
|
120
|
+
myLibrary.setLibraryPath('./modules.d');
|
|
121
121
|
```
|
|
122
122
|
|
|
123
123
|
### 3. **Shared Resource Definition**
|
|
@@ -127,33 +127,33 @@ const passThroughParameters = {
|
|
|
127
127
|
config: appConfig,
|
|
128
128
|
database: dbConnection,
|
|
129
129
|
logger: logger
|
|
130
|
-
};
|
|
130
|
+
}; //provided by loadModules() in the initialization object
|
|
131
131
|
```
|
|
132
132
|
|
|
133
133
|
### 4. **Module Loading**
|
|
134
134
|
|
|
135
135
|
```javascript
|
|
136
136
|
// Synchronous
|
|
137
|
-
|
|
137
|
+
myLibrary.loadModules({ passThroughParameters });
|
|
138
138
|
|
|
139
139
|
// Asynchronous
|
|
140
|
-
|
|
140
|
+
myLibrary.loadModules({ passThroughParameters }, callback);
|
|
141
141
|
```
|
|
142
142
|
|
|
143
143
|
### 5. **Library Sealing**
|
|
144
144
|
|
|
145
145
|
```javascript
|
|
146
|
-
|
|
146
|
+
myLibrary.seal(); // Prevents further modifications
|
|
147
147
|
```
|
|
148
148
|
|
|
149
149
|
### 6. **Module Usage**
|
|
150
150
|
|
|
151
151
|
```javascript
|
|
152
152
|
// If you have modules.d/processOrder.js
|
|
153
|
-
|
|
153
|
+
myLibrary.processOrder(orderData);
|
|
154
154
|
|
|
155
155
|
// If you have modules.d/sendEmail.js
|
|
156
|
-
|
|
156
|
+
myLibrary.sendEmail(recipient, message);
|
|
157
157
|
```
|
|
158
158
|
|
|
159
159
|
## Module Structure
|
|
@@ -201,13 +201,7 @@ module.exports = moduleFunction({ moduleName });
|
|
|
201
201
|
npm install qtools-library-dot-d
|
|
202
202
|
```
|
|
203
203
|
|
|
204
|
-
2. **
|
|
205
|
-
|
|
206
|
-
```bash
|
|
207
|
-
npm start
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
3. **Create your own modules:**
|
|
204
|
+
2. **Create your own modules:**
|
|
211
205
|
|
|
212
206
|
- Add `.js` files to `demoModules_DotD/`
|
|
213
207
|
- Follow the module pattern shown in the examples
|
|
@@ -235,7 +229,7 @@ This pattern is used extensively in the qtools ecosystem for building scalable,
|
|
|
235
229
|
|
|
236
230
|
## HISTORY
|
|
237
231
|
|
|
238
|
-
v1.
|
|
232
|
+
v1.09 - fixed broken error handling when library file path is bad; added demonstration application
|
|
233
|
+
v1.08 - updated README (several times)
|
|
239
234
|
v1.05 - cleaned up toString() report, returns exception list (or err if callback) if needed, added qtools-functional-library
|
|
240
235
|
v1.04 - Now tolerates (and reports) directories and files that are not modules.
|
|
241
|
-
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# Dynamic dotD Libraries with qtools-library-dot-d
|
|
2
|
+
|
|
3
|
+
This project demonstrates the **qtools-library-dot-d** system for creating dynamic, modular libraries in Node.js. The dotD (dot-D) pattern provides a powerful way to build extensible applications through automatic module discovery and loading.
|
|
4
|
+
|
|
5
|
+
## What is qtools-library-dot-d?
|
|
6
|
+
|
|
7
|
+
**qtools-library-dot-d** is a Node.js library that enables dynamic module loading from directories. It automatically discovers JavaScript files in specified directories and makes them available as methods on a library object, creating a plugin-like architecture without the complexity of traditional plugin systems.
|
|
8
|
+
|
|
9
|
+
## The dotD Pattern
|
|
10
|
+
|
|
11
|
+
The "dotD" naming convention (short for "dot-D") refers to directories that contain dynamically loadable modules:
|
|
12
|
+
|
|
13
|
+
- `modules.d/` - Directory containing module files
|
|
14
|
+
- `endpoints.d/` - Directory containing API endpoint modules
|
|
15
|
+
- `accessPoints.d/` - Directory containing data access modules
|
|
16
|
+
- `mappers.d/` - Directory containing data mapping modules
|
|
17
|
+
|
|
18
|
+
Each `.js` file in a dotD directory becomes a method on the library object, with the filename determining the method name.
|
|
19
|
+
|
|
20
|
+
## Why Use Dynamic dotD Libraries?
|
|
21
|
+
|
|
22
|
+
### 1. **Automatic Module Discovery**
|
|
23
|
+
|
|
24
|
+
No need to manually import or register modules. Simply add a `.js` file to the dotD directory and it's automatically available.
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
// Traditional approach - manual imports
|
|
28
|
+
const module1 = require('./modules/module1');
|
|
29
|
+
const module2 = require('./modules/module2');
|
|
30
|
+
const module3 = require('./modules/module3');
|
|
31
|
+
|
|
32
|
+
// dotD approach - automatic discovery
|
|
33
|
+
const library = qtLibDotD({ libraryName: 'myLibrary' });
|
|
34
|
+
library.setLibraryPath('./modules.d');
|
|
35
|
+
library.loadModules();
|
|
36
|
+
// All modules in modules.d/ are now available as library.moduleName()
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 2. **Plugin Architecture**
|
|
40
|
+
|
|
41
|
+
Create extensible applications where new functionality can be added by simply dropping files into directories.
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
// Add new functionality by creating a new file
|
|
45
|
+
// modules.d/newFeature.js -> library.newFeature()
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 3. **Shared Resources**
|
|
49
|
+
|
|
50
|
+
Pass common resources (configuration, database connections, utilities) to all modules through `passThroughParameters`.
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
const passThroughParameters = {
|
|
54
|
+
config: getConfig(),
|
|
55
|
+
database: dbConnection,
|
|
56
|
+
logger: xLog,
|
|
57
|
+
utilities: commonUtils
|
|
58
|
+
};
|
|
59
|
+
library.loadModules({ passThroughParameters });
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 4. **Clean Separation of Concerns**
|
|
63
|
+
|
|
64
|
+
Each module is self-contained and focused on a single responsibility, making code easier to maintain and test.
|
|
65
|
+
|
|
66
|
+
### 5. **Runtime Flexibility**
|
|
67
|
+
|
|
68
|
+
Modules can be loaded synchronously or asynchronously, and the library can be sealed to prevent modifications after loading.
|
|
69
|
+
|
|
70
|
+
## Real-World Use Cases
|
|
71
|
+
|
|
72
|
+
### API Endpoint Management
|
|
73
|
+
|
|
74
|
+
```javascript
|
|
75
|
+
// endpoints.d/userEndpoints.js
|
|
76
|
+
// endpoints.d/productEndpoints.js
|
|
77
|
+
// endpoints.d/orderEndpoints.js
|
|
78
|
+
// Each file defines related API endpoints
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Data Access Layer
|
|
82
|
+
|
|
83
|
+
```javascript
|
|
84
|
+
// accessPoints.d/getUserData.js
|
|
85
|
+
// accessPoints.d/saveUserData.js
|
|
86
|
+
// accessPoints.d/deleteUserData.js
|
|
87
|
+
// Each file handles specific data operations
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Business Logic Modules
|
|
91
|
+
|
|
92
|
+
```javascript
|
|
93
|
+
// processors.d/validateOrder.js
|
|
94
|
+
// processors.d/calculateTax.js
|
|
95
|
+
// processors.d/sendNotification.js
|
|
96
|
+
// Each file contains specific business logic
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### CLI Command Tools
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
// commands.d/deploy.js
|
|
103
|
+
// commands.d/backup.js
|
|
104
|
+
// commands.d/migrate.js
|
|
105
|
+
// Each file implements a CLI command
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## How It Works
|
|
109
|
+
|
|
110
|
+
### 1. **Library Creation**
|
|
111
|
+
|
|
112
|
+
```javascript
|
|
113
|
+
const qtLibDotD = require('qtools-library-dot-d');
|
|
114
|
+
const library = qtLibDotD({ libraryName: 'myLibrary' });
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 2. **Module Directory Setup**
|
|
118
|
+
|
|
119
|
+
```javascript
|
|
120
|
+
library.setLibraryPath('./modules.d');
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### 3. **Shared Resource Definition**
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
const passThroughParameters = {
|
|
127
|
+
config: appConfig,
|
|
128
|
+
database: dbConnection,
|
|
129
|
+
logger: logger
|
|
130
|
+
};
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### 4. **Module Loading**
|
|
134
|
+
|
|
135
|
+
```javascript
|
|
136
|
+
// Synchronous
|
|
137
|
+
library.loadModules({ passThroughParameters });
|
|
138
|
+
|
|
139
|
+
// Asynchronous
|
|
140
|
+
library.loadModules({ passThroughParameters }, callback);
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### 5. **Library Sealing**
|
|
144
|
+
|
|
145
|
+
```javascript
|
|
146
|
+
library.seal(); // Prevents further modifications
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 6. **Module Usage**
|
|
150
|
+
|
|
151
|
+
```javascript
|
|
152
|
+
// If you have modules.d/processOrder.js
|
|
153
|
+
library.processOrder(orderData);
|
|
154
|
+
|
|
155
|
+
// If you have modules.d/sendEmail.js
|
|
156
|
+
library.sendEmail(recipient, message);
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Module Structure
|
|
160
|
+
|
|
161
|
+
Every dotD module follows this pattern:
|
|
162
|
+
|
|
163
|
+
```javascript
|
|
164
|
+
const moduleName = __filename.replace(__dirname + '/', '').replace(/.js$/, '');
|
|
165
|
+
|
|
166
|
+
const moduleFunction = ({ moduleName } = {}) => ({ dotD, passThroughParameters } = {}) => {
|
|
167
|
+
|
|
168
|
+
const workingFunction = (/* your parameters */) => {
|
|
169
|
+
// Access shared resources
|
|
170
|
+
const config = passThroughParameters.config;
|
|
171
|
+
const logger = passThroughParameters.logger;
|
|
172
|
+
|
|
173
|
+
// Your module logic here
|
|
174
|
+
|
|
175
|
+
return result;
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// Register the function
|
|
179
|
+
dotD.library.add(moduleName, workingFunction);
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
module.exports = moduleFunction({ moduleName });
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Benefits Over Traditional Approaches
|
|
186
|
+
|
|
187
|
+
| Traditional | dotD Libraries |
|
|
188
|
+
| --------------------- | --------------------------- |
|
|
189
|
+
| Manual imports | Automatic discovery |
|
|
190
|
+
| Tight coupling | Loose coupling |
|
|
191
|
+
| Hard to extend | Easy to extend |
|
|
192
|
+
| Configuration in code | Configuration through files |
|
|
193
|
+
| Monolithic | Modular |
|
|
194
|
+
| Static structure | Dynamic structure |
|
|
195
|
+
|
|
196
|
+
## Getting Started
|
|
197
|
+
|
|
198
|
+
1. **Install the dependency:**
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
npm install qtools-library-dot-d
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
2. **Run the example:**
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
npm start
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
3. **Create your own modules:**
|
|
211
|
+
|
|
212
|
+
- Add `.js` files to `demoModules_DotD/`
|
|
213
|
+
- Follow the module pattern shown in the examples
|
|
214
|
+
- Access shared resources via `passThroughParameters`
|
|
215
|
+
|
|
216
|
+
## Advanced Features
|
|
217
|
+
|
|
218
|
+
- **Async module loading** for modules that need initialization
|
|
219
|
+
- **Error handling** during module loading
|
|
220
|
+
- **Library introspection** with `toString()` and `qtdProcessLog()`
|
|
221
|
+
- **Multiple libraries** in the same application
|
|
222
|
+
- **Nested module structures** for complex applications
|
|
223
|
+
|
|
224
|
+
## Integration with Larger Systems
|
|
225
|
+
|
|
226
|
+
The dotD pattern works particularly well in:
|
|
227
|
+
|
|
228
|
+
- **Web frameworks** (Express, Koa) for route organization
|
|
229
|
+
- **API systems** for endpoint management
|
|
230
|
+
- **CLI tools** for command organization
|
|
231
|
+
- **Microservices** for feature modularity
|
|
232
|
+
- **Plugin systems** for extensible applications
|
|
233
|
+
|
|
234
|
+
This pattern is used extensively in the qtools ecosystem for building scalable, maintainable Node.js applications.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
// Suppress punycode deprecation warning
|
|
4
|
+
process.noDeprecation = true;
|
|
5
|
+
|
|
6
|
+
const moduleName = __filename.replace(__dirname + '/', '').replace(/.js$/, ''); //this just seems to come in handy a lot
|
|
7
|
+
|
|
8
|
+
//START OF moduleFunction() ============================================================
|
|
9
|
+
// DOTD MODULE STRUCTURE GUIDE
|
|
10
|
+
// ============================
|
|
11
|
+
// Every dotD module follows this exact pattern:
|
|
12
|
+
// 1. Export a function that takes { moduleName } and returns another function
|
|
13
|
+
// 2. The returned function receives { dotD, passThroughParameters }
|
|
14
|
+
// 3. Define your working function that implements the module's functionality
|
|
15
|
+
// 4. Add the working function to the library using dotD.library.add()
|
|
16
|
+
// 5. The module name (from filename) becomes the method name on the library
|
|
17
|
+
|
|
18
|
+
const moduleFunction = ({ moduleName } = {}) => ({ dotD, passThroughParameters } = {}) => {
|
|
19
|
+
|
|
20
|
+
// STEP 1: Define your module's main functionality
|
|
21
|
+
// This function will be called when someone uses libraryInstance.demo1()
|
|
22
|
+
const workingFunction = () => {
|
|
23
|
+
// ACCESS SHARED DATA: Use passThroughParameters for shared resources
|
|
24
|
+
console.log(`${passThroughParameters.message} [${moduleName}]`);
|
|
25
|
+
|
|
26
|
+
// RETURN VALUES: Your function can return any value
|
|
27
|
+
return 'hello';
|
|
28
|
+
|
|
29
|
+
// COMMON PATTERNS:
|
|
30
|
+
// - Access shared config: passThroughParameters.config
|
|
31
|
+
// - Use shared logger: passThroughParameters.xLog('message')
|
|
32
|
+
// - Access database: passThroughParameters.database.query(...)
|
|
33
|
+
// - Call shared utilities: passThroughParameters.utilityFunction()
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// STEP 2: Register the function with the library
|
|
37
|
+
// The moduleName (from filename) becomes the method name
|
|
38
|
+
// Example: demo1.js creates libraryInstance.demo1()
|
|
39
|
+
dotD.library.add(moduleName, workingFunction);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
//END OF moduleFunction() ============================================================
|
|
43
|
+
|
|
44
|
+
// STEP 3: Export the configured module function
|
|
45
|
+
// This runs immediately when the module is loaded
|
|
46
|
+
module.exports = moduleFunction({ moduleName }); //runs it right now
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
// Suppress punycode deprecation warning
|
|
4
|
+
process.noDeprecation = true;
|
|
5
|
+
|
|
6
|
+
const moduleName = __filename.replace(__dirname + '/', '').replace(/.js$/, ''); //this just seems to come in handy a lot
|
|
7
|
+
|
|
8
|
+
//START OF moduleFunction() ============================================================
|
|
9
|
+
// DOTD MODULE WITH PARAMETERS AND SHARED FUNCTIONS
|
|
10
|
+
// =================================================
|
|
11
|
+
// This example shows how to:
|
|
12
|
+
// 1. Accept parameters in your module functions
|
|
13
|
+
// 2. Use shared functions from passThroughParameters
|
|
14
|
+
// 3. Combine local logic with shared utilities
|
|
15
|
+
|
|
16
|
+
const moduleFunction = ({ moduleName } = {}) => ({ dotD, passThroughParameters } = {}) => {
|
|
17
|
+
|
|
18
|
+
// STEP 1: Define a function that accepts parameters
|
|
19
|
+
// This demonstrates how module functions can receive arguments
|
|
20
|
+
const workingFunction = (arg1, arg2) => {
|
|
21
|
+
// USING SHARED FUNCTIONS: Call functions from passThroughParameters
|
|
22
|
+
// In this example, 'add' was passed in from the main library setup
|
|
23
|
+
const result = passThroughParameters.add(arg1, arg2);
|
|
24
|
+
|
|
25
|
+
console.log(`Pass Through Function: ${arg1}+${arg2}=${result} [${moduleName}]`);
|
|
26
|
+
|
|
27
|
+
// COMMON PATTERNS WITH PARAMETERS:
|
|
28
|
+
// - Validation: if (!arg1 || !arg2) throw new Error('Missing arguments');
|
|
29
|
+
// - Default values: arg1 = arg1 || defaultValue;
|
|
30
|
+
// - Type checking: if (typeof arg1 !== 'number') return null;
|
|
31
|
+
// - Using shared config: const timeout = passThroughParameters.config.timeout;
|
|
32
|
+
// - Logging with shared logger: passThroughParameters.xLog(`Processing ${arg1}, ${arg2}`);
|
|
33
|
+
|
|
34
|
+
return result; // Return meaningful data
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// STEP 2: Register the function (same as demo1)
|
|
38
|
+
dotD.library.add(moduleName, workingFunction);
|
|
39
|
+
|
|
40
|
+
// ALTERNATIVE PATTERNS:
|
|
41
|
+
// You could also add multiple functions from one module:
|
|
42
|
+
// dotD.library.add(`${moduleName}Sync`, syncVersion);
|
|
43
|
+
// dotD.library.add(`${moduleName}Async`, asyncVersion);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
//END OF moduleFunction() ============================================================
|
|
47
|
+
|
|
48
|
+
module.exports = moduleFunction({ moduleName }); //runs it right now
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
// Suppress punycode deprecation warning
|
|
4
|
+
process.noDeprecation = true;
|
|
5
|
+
|
|
6
|
+
const moduleName = __filename.replace(__dirname + '/', '').replace(/.js$/, ''); //this just seems to come in handy a lot
|
|
7
|
+
|
|
8
|
+
// const qt = require('qtools-functional-library'); //also exposes qtLog(); qt.help({printOutput:true, queryString:'.*', sendJson:false});
|
|
9
|
+
|
|
10
|
+
const os = require('os');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
|
|
14
|
+
// DYNAMIC LIBRARY CREATION GUIDE
|
|
15
|
+
// ===============================
|
|
16
|
+
// This example demonstrates how to create a dynamic dotD library using qtools-library-dot-d
|
|
17
|
+
//
|
|
18
|
+
// KEY CONCEPTS:
|
|
19
|
+
// 1. dotD libraries automatically load modules from a specified directory
|
|
20
|
+
// 2. All .js files in the dotD directory become available as methods on the library object
|
|
21
|
+
// 3. Modules receive shared data through passThroughParameters
|
|
22
|
+
// 4. Libraries can be loaded synchronously or asynchronously
|
|
23
|
+
// 5. Always call seal() after loading to finalize the library
|
|
24
|
+
|
|
25
|
+
const qtLibDotD = require('qtools-library-dot-d');
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
//START OF moduleFunction() ============================================================
|
|
29
|
+
const moduleFunction =
|
|
30
|
+
({ moduleName } = {}) =>
|
|
31
|
+
({ unused } = {}) => {
|
|
32
|
+
|
|
33
|
+
// ========================================================================
|
|
34
|
+
// SYNCHRONOUS DEMO - Use this pattern for simple, immediate library creation
|
|
35
|
+
|
|
36
|
+
const synchronousDemo = () => {
|
|
37
|
+
// STEP 1: Create the library instance with a descriptive name
|
|
38
|
+
const demoDotD = qtLibDotD({
|
|
39
|
+
libraryName: 'demoDotD', // This name appears in logs and debugging output
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// STEP 2: Define the path to your dotD modules directory
|
|
43
|
+
// Convention: Use 'ModuleName_DotD' or 'moduleName.d' for the directory name
|
|
44
|
+
const libraryModulesPath = path.join(__dirname, 'demoModules_DotD');
|
|
45
|
+
|
|
46
|
+
// STEP 3: Define passThroughParameters - shared data/functions for all modules
|
|
47
|
+
// These parameters are available in every module via the passThroughParameters argument
|
|
48
|
+
// Common uses: configuration, shared utilities, database connections, logging functions
|
|
49
|
+
const passThroughParameters = {
|
|
50
|
+
message: 'Hello from a dotDlib module', // Example: shared message
|
|
51
|
+
add: (a, b) => a + b, // Example: shared utility function
|
|
52
|
+
// Add your own shared resources here:
|
|
53
|
+
// config: getConfig(),
|
|
54
|
+
// logger: xLog,
|
|
55
|
+
// database: dbConnection,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// STEP 4: Set the library path and load modules
|
|
59
|
+
demoDotD.setLibraryPath(libraryModulesPath);
|
|
60
|
+
demoDotD.loadModules({ passThroughParameters }); // Synchronous loading
|
|
61
|
+
|
|
62
|
+
// STEP 5: Seal the library to prevent further modifications
|
|
63
|
+
demoDotD.seal();
|
|
64
|
+
|
|
65
|
+
// DEBUGGING: Uncomment to see detailed loading information
|
|
66
|
+
// console.log(demoDotD.qtdProcessLog());
|
|
67
|
+
|
|
68
|
+
// INSPECTION: See what modules were loaded
|
|
69
|
+
console.log(demoDotD.toString());
|
|
70
|
+
|
|
71
|
+
// USAGE: Call your dynamically loaded modules
|
|
72
|
+
// Each .js file in the dotD directory becomes a method with the same name
|
|
73
|
+
demoDotD.demo1(); // Calls demoModules_DotD/demo1.js
|
|
74
|
+
demoDotD.demo2(10, 7); // Calls demoModules_DotD/demo2.js with arguments
|
|
75
|
+
};
|
|
76
|
+
console.log(`SYNCHRONOUS DEMO =====================================`);
|
|
77
|
+
synchronousDemo();
|
|
78
|
+
|
|
79
|
+
// ========================================================================
|
|
80
|
+
// ASYNCHRONOUS DEMO - Use this pattern when modules need async initialization
|
|
81
|
+
|
|
82
|
+
const asynchronousDemo = (callback) => {
|
|
83
|
+
// Create a local callback to handle async completion
|
|
84
|
+
const localCallback = (err) => {
|
|
85
|
+
// IMPORTANT: Always seal after async loading completes
|
|
86
|
+
demoDotD.seal();
|
|
87
|
+
callback(err, demoDotD);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// STEP 1: Create the library instance
|
|
91
|
+
const demoDotD = qtLibDotD({
|
|
92
|
+
libraryName: 'demoDotD',
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// STEP 2: Define module directory path
|
|
96
|
+
const libraryModulesPath = path.join(__dirname, 'demoModules_DotD');
|
|
97
|
+
|
|
98
|
+
// STEP 3: Define shared parameters (same as synchronous version)
|
|
99
|
+
const passThroughParameters = {
|
|
100
|
+
message: 'Hello from a dotDlib module',
|
|
101
|
+
add: (a, b) => a + b,
|
|
102
|
+
// For async loading, you might include:
|
|
103
|
+
// database: await dbConnection(),
|
|
104
|
+
// config: await loadConfig(),
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// STEP 4: Set path and load modules asynchronously
|
|
108
|
+
demoDotD.setLibraryPath(libraryModulesPath);
|
|
109
|
+
demoDotD.loadModules({ passThroughParameters }, localCallback); // Async loading with callback
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
console.log(`\n\nASYNCHRONOUS DEMO =====================================`);
|
|
113
|
+
|
|
114
|
+
// Define callback to handle async completion
|
|
115
|
+
const callback = (err, demoDotD) => {
|
|
116
|
+
if (err) {
|
|
117
|
+
console.error('Error loading library:', err);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
// Library is now ready to use
|
|
121
|
+
console.log(demoDotD.toString());
|
|
122
|
+
demoDotD.demo1();
|
|
123
|
+
demoDotD.demo2(10, 7);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// Start async loading
|
|
127
|
+
asynchronousDemo(callback);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
//END OF moduleFunction() ============================================================
|
|
131
|
+
|
|
132
|
+
module.exports = moduleFunction({ moduleName })({});
|
|
133
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "libdotd_example",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"lockfileVersion": 3,
|
|
5
|
+
"requires": true,
|
|
6
|
+
"packages": {
|
|
7
|
+
"node_modules/qtools-asynchronous-pipe-plus": {
|
|
8
|
+
"version": "1.0.5",
|
|
9
|
+
"resolved": "https://registry.npmjs.org/qtools-asynchronous-pipe-plus/-/qtools-asynchronous-pipe-plus-1.0.5.tgz",
|
|
10
|
+
"integrity": "sha512-ejueK++dNl6AJL0OK14zTewXDg1+Wq8zFknI83THmgR9rNTB7EfngLt031/hkkc3/VpnqdaeO7mNqnu6YAzgIQ=="
|
|
11
|
+
},
|
|
12
|
+
"node_modules/qtools-functional-library": {
|
|
13
|
+
"version": "2.0.4",
|
|
14
|
+
"resolved": "https://registry.npmjs.org/qtools-functional-library/-/qtools-functional-library-2.0.4.tgz",
|
|
15
|
+
"integrity": "sha512-noztSkJI37xcOTer5HVgOnuY/eZ1FeqtSvlpzhmSq7jjT6dQCQjIzwjoe1GqHc5Dt9Os+OFawAUz3hMpO4V1ng==",
|
|
16
|
+
"license": "ISC"
|
|
17
|
+
},
|
|
18
|
+
"node_modules/qtools-library-dot-d": {
|
|
19
|
+
"version": "1.0.5",
|
|
20
|
+
"resolved": "https://registry.npmjs.org/qtools-library-dot-d/-/qtools-library-dot-d-1.0.5.tgz",
|
|
21
|
+
"integrity": "sha512-MEkrc1NCk8OleAlUPrlJ4Pl8z9v4gOEQt6PIjTc7r16x4StnfQ/ntTfaFF2kS4pi6O1zY1YBpB8vG1q0rdwTcQ==",
|
|
22
|
+
"license": "ISC",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"qtools-asynchronous-pipe-plus": "^1.0.2",
|
|
25
|
+
"qtools-functional-library": "^2.0.4"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|