fable-serviceproviderbase 3.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Steven Velozo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # Fable Service Provider
2
+
3
+ A very basic set of base classes to provide the interface for Fable services.
4
+ This is used for instantiating connections to databases, extending core
5
+ services and whatever other services.
6
+
7
+ Some service types Fable provides out of the box:
8
+
9
+ * settings
10
+ * logging
11
+ * uuid
12
+ * templating
13
+
14
+
15
+ ## Basic Services
16
+
17
+ There are two types of services -- just requiring the class provides a base
18
+ class for most services. The constructor for this type takes in a fully
19
+ initialized fable object.
20
+
21
+ ```
22
+ const libFableServiceProviderBase = require('fable-serviceproviderbase');
23
+
24
+ class SimpleService extends libFableServiceProviderBase
25
+ {
26
+ constructor(pFable, pOptions, pServiceHash)
27
+ {
28
+ super(pFable, pOptions, pServiceHash);
29
+
30
+ this.serviceType = 'SimpleService';
31
+ }
32
+
33
+ doSomething()
34
+ {
35
+ this.fable.log.info(`SimpleService ${this.UUID}::${this.Hash} is doing something.`);
36
+ }
37
+ }
38
+ ```
39
+
40
+ ## Core Pre-initialization Services
41
+
42
+ For some service types, we want to instantiate behaviors before the fable
43
+ class has been initialized. These use a special service base that defers
44
+ the connection of an initialized fable object until after it's created.
45
+
46
+ The one caveat here is the fable service doesn't provide consistent settings,
47
+ log or uuid functionality until they have been initialized and mapped in.
48
+
49
+ If you want to use this base class, please refer to the fable service
50
+ manager code as well to get a good understanding of how initialization
51
+ differs from the basic services.
52
+
53
+
54
+ ```
55
+ const libFableServiceProviderBase = require('fable-serviceproviderbase');
56
+
57
+ class SimpleService extends libFableServiceProviderBase
58
+ {
59
+ constructor(pFable, pOptions, pServiceHash)
60
+ {
61
+ super(pFable, pOptions, pServiceHash);
62
+
63
+ this.serviceType = 'SimpleService';
64
+ }
65
+
66
+ doSomething()
67
+ {
68
+ this.fable.log.info(`SimpleService ${this.UUID}::${this.Hash} is doing something.`);
69
+ }
70
+ }
71
+ ```
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "fable-serviceproviderbase",
3
+ "version": "3.0.0",
4
+ "description": "Simple base classes for fable services.",
5
+ "main": "source/Fable-ServiceProviderBase.js",
6
+ "scripts": {
7
+ "start": "node source/Fable-ServiceProviderBase.js",
8
+ "coverage": "./node_modules/.bin/nyc --reporter=lcov --reporter=text-lcov ./node_modules/mocha/bin/_mocha -- -u tdd -R spec",
9
+ "test": "./node_modules/.bin/mocha -u tdd -R spec"
10
+ },
11
+ "mocha": {
12
+ "diff": true,
13
+ "extension": [
14
+ "js"
15
+ ],
16
+ "package": "./package.json",
17
+ "reporter": "spec",
18
+ "slow": "75",
19
+ "timeout": "5000",
20
+ "ui": "tdd",
21
+ "watch-files": [
22
+ "source/**/*.js",
23
+ "test/**/*.js"
24
+ ],
25
+ "watch-ignore": [
26
+ "lib/vendor"
27
+ ]
28
+ },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/stevenvelozo/fable-serviceproviderbase.git"
32
+ },
33
+ "keywords": [
34
+ "entity",
35
+ "behavior"
36
+ ],
37
+ "author": "Steven Velozo <steven@velozo.com> (http://velozo.com/)",
38
+ "license": "MIT",
39
+ "bugs": {
40
+ "url": "https://github.com/stevenvelozo/fable-serviceproviderbase/issues"
41
+ },
42
+ "homepage": "https://github.com/stevenvelozo/fable-serviceproviderbase",
43
+ "devDependencies": {
44
+ "chai": "4.3.7",
45
+ "fable": "^3.0.27",
46
+ "mocha": "10.2.0",
47
+ "nyc": "^15.1.0"
48
+ }
49
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Fable Core Pre-initialization Service Base
3
+ *
4
+ * For a couple services, we need to be able to instantiate them before the Fable object is fully initialized.
5
+ * This is a base class for those services.
6
+ *
7
+ * @license MIT
8
+ * @author <steven@velozo.com>
9
+ */
10
+
11
+ class FableCoreServiceProviderBase
12
+ {
13
+ constructor(pOptions, pServiceHash)
14
+ {
15
+ this.fable = false;
16
+
17
+ this.options = (typeof(pOptions) === 'object') ? pOptions : {};
18
+
19
+ this.serviceType = 'Unknown';
20
+
21
+ // The hash will be a non-standard UUID ... the UUID service uses this base class!
22
+ this.UUID = `CORESVC-${Math.floor((Math.random() * (99999 - 10000)) + 10000)}`;
23
+
24
+ this.Hash = (typeof(pServiceHash) === 'string') ? pServiceHash : `${this.UUID}`;
25
+ }
26
+
27
+ // After fable is initialized, it would be expected to be wired in as a normal service.
28
+ connectFable(pFable)
29
+ {
30
+ this.fable = pFable;
31
+
32
+ return true;
33
+ }
34
+ }
35
+
36
+ module.exports = FableCoreServiceProviderBase;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Fable Service Base
3
+ * @license MIT
4
+ * @author <steven@velozo.com>
5
+ */
6
+
7
+ class FableServiceProviderBase
8
+ {
9
+ constructor(pFable, pOptions, pServiceHash)
10
+ {
11
+ this.fable = pFable;
12
+
13
+ this.options = (typeof(pOptions) === 'object') ? pOptions : {};
14
+
15
+ this.serviceType = 'Unknown';
16
+
17
+ this.UUID = pFable.getUUID();
18
+
19
+ this.Hash = (typeof(pServiceHash) === 'string') ? pServiceHash : `${this.UUID}`;
20
+ }
21
+ }
22
+
23
+ module.exports = FableServiceProviderBase;
24
+
25
+ module.exports.CoreServiceProviderBase = require('./Fable-ServiceProviderBase-Preinit.js');
@@ -0,0 +1,279 @@
1
+ /**
2
+ * Unit tests for Fable Servi
3
+ *
4
+ * @license MIT
5
+ *
6
+ * @author Steven Velozo <steven@velozo.com>
7
+ */
8
+
9
+ const libFable = require('fable');
10
+ const libFableServiceProviderBase = require('../source/Fable-ServiceProviderBase.js');
11
+
12
+ const Chai = require("chai");
13
+ const Expect = Chai.expect;
14
+
15
+ class SimpleService extends libFableServiceProviderBase
16
+ {
17
+ constructor(pFable, pOptions, pServiceHash)
18
+ {
19
+ super(pFable, pOptions, pServiceHash);
20
+
21
+ this.serviceType = 'SimpleService';
22
+ }
23
+
24
+ doSomething()
25
+ {
26
+ this.fable.log.info(`SimpleService ${this.UUID}::${this.Hash} is doing something.`);
27
+ }
28
+ }
29
+
30
+ class MockDatabaseService extends libFableServiceProviderBase
31
+ {
32
+ constructor(pFable, pOptions, pServiceHash)
33
+ {
34
+ super(pFable, pOptions, pServiceHash);
35
+
36
+ this.serviceType = 'MockDatabaseService';
37
+ }
38
+
39
+ connect()
40
+ {
41
+ this.fable.log.info(`MockDatabaseService ${this.UUID}::${this.Hash} is connecting to a database.`);
42
+ }
43
+
44
+ commit(pRecord)
45
+ {
46
+ this.fable.log.info(`MockDatabaseService ${this.UUID}::${this.Hash} is committing a record ${pRecord}.`);
47
+ }
48
+ }
49
+
50
+ class MockCoreService extends libFableServiceProviderBase.CoreServiceProviderBase
51
+ {
52
+ constructor(pOptions, pServiceHash)
53
+ {
54
+ super(pOptions, pServiceHash);
55
+
56
+ this.serviceType = 'MockCoreService';
57
+ }
58
+
59
+ // Core services should be able to provide their behaviors before the Fable object is fully initialized.
60
+ magicBehavior(pData)
61
+ {
62
+ console.log(`MockCoreService ${this.UUID}::${this.Hash} is doing something magical with ${pData}.`);
63
+ }
64
+ }
65
+
66
+ suite
67
+ (
68
+ 'Fable Service Manager',
69
+ function()
70
+ {
71
+ var testFable = false;
72
+
73
+ setup
74
+ (
75
+ function()
76
+ {
77
+ }
78
+ );
79
+
80
+ suite
81
+ (
82
+ 'Service Manager',
83
+ function()
84
+ {
85
+ test
86
+ (
87
+ 'Manually initialize a Service',
88
+ function()
89
+ {
90
+ testFable = new libFable();
91
+
92
+ let tmpSimpleService = new SimpleService(testFable, {SomeOption: true});
93
+
94
+ tmpSimpleService.doSomething();
95
+
96
+ Expect(tmpSimpleService.Hash).to.be.a('string');
97
+ }
98
+ );
99
+ test
100
+ (
101
+ 'Register a Service',
102
+ function()
103
+ {
104
+ testFable = new libFable();
105
+ testFable.serviceManager.addServiceType('SimpleService');
106
+ testFable.serviceManager.instantiateServiceProvider('SimpleService', {SomeOption: true}, 'SimpleService-123');
107
+
108
+ Expect(testFable.serviceManager.services['SimpleService']['SimpleService-123']).to.be.an('object');
109
+ }
110
+ );
111
+ test
112
+ (
113
+ 'Use the Default Service',
114
+ function()
115
+ {
116
+ testFable = new libFable();
117
+ testFable.serviceManager.addServiceType('SimpleService', SimpleService);
118
+ testFable.serviceManager.instantiateServiceProvider('SimpleService', {SomeOption: true}, 'SimpleService-123');
119
+
120
+ Expect(testFable.serviceManager.services['SimpleService']['SimpleService-123']).to.be.an('object');
121
+
122
+ Expect(testFable.serviceManager.defaultServices['SimpleService']).to.be.an('object');
123
+
124
+ testFable.serviceManager.defaultServices.SimpleService.doSomething();
125
+
126
+ Expect(testFable.serviceManager.defaultServices['SimpleService'].Hash).to.equal('SimpleService-123');
127
+ }
128
+ );
129
+ test
130
+ (
131
+ 'Use the Default Service with a different hash',
132
+ function()
133
+ {
134
+ let testFable = new libFable({});
135
+
136
+ testFable.serviceManager.addServiceType('SimpleService', SimpleService);
137
+
138
+ testFable.serviceManager.instantiateServiceProvider('SimpleService', {SomeOption: true}, 'SimpleService-13');
139
+
140
+ testFable.serviceManager.services['SimpleService']['SimpleService-13'].doSomething();
141
+
142
+ Expect(testFable.serviceManager.services['SimpleService']['SimpleService-13']).to.be.an('object');
143
+ }
144
+ );
145
+
146
+ test
147
+ (
148
+ 'Instantiate a service without registering it to Fable',
149
+ function()
150
+ {
151
+ let testFable = new libFable({});
152
+
153
+ testFable.serviceManager.addServiceType('SimpleService', SimpleService);
154
+
155
+ let tmpService = testFable.serviceManager.instantiateServiceProviderWithoutRegistration('SimpleService', {SomeOption: true}, 'SimpleService-99');
156
+
157
+ Expect(testFable.services.SimpleService['SimpleService-99']).to.be.an('undefined');
158
+
159
+ Expect(tmpService).to.be.an('object');
160
+ }
161
+ );
162
+
163
+ test
164
+ (
165
+ 'Change the default service provider',
166
+ function()
167
+ {
168
+ let testFable = new libFable({});
169
+
170
+ testFable.serviceManager.addServiceType('SimpleService', SimpleService);
171
+ testFable.serviceManager.addServiceType('DatabaseService', MockDatabaseService);
172
+
173
+ testFable.serviceManager.instantiateServiceProvider('SimpleService', {SomeOption: true});
174
+ testFable.serviceManager.defaultServices.SimpleService.doSomething();
175
+
176
+ testFable.serviceManager.instantiateServiceProvider('DatabaseService', {ConnectionString: 'mongodb://localhost:27017/test'}, 'PrimaryConnection');
177
+
178
+ Expect(testFable.serviceManager.defaultServices.DatabaseService.Hash).to.equal('PrimaryConnection');
179
+
180
+ testFable.serviceManager.instantiateServiceProvider('DatabaseService', {ConnectionString: 'mongodb://localhost:27017/test'}, 'SecondaryConnection');
181
+
182
+ Expect(testFable.serviceManager.defaultServices.DatabaseService.Hash).to.equal('PrimaryConnection');
183
+
184
+ testFable.serviceManager.defaultServices.DatabaseService.connect();
185
+ testFable.serviceManager.defaultServices.DatabaseService.commit('Test Record');
186
+
187
+ testFable.serviceManager.setDefaultServiceInstantiation('DatabaseService', 'SecondaryConnection');
188
+
189
+ testFable.serviceManager.defaultServices.DatabaseService.connect();
190
+ testFable.serviceManager.defaultServices.DatabaseService.commit('Another Test Record');
191
+
192
+ Expect(testFable.serviceManager.defaultServices.DatabaseService.Hash).to.equal('SecondaryConnection');
193
+ }
194
+ );
195
+
196
+ test
197
+ (
198
+ 'Construct a core service before Fable is initialized',
199
+ function()
200
+ {
201
+ let tmpCoreService = new MockCoreService({SomeOption: true});
202
+
203
+ Expect(tmpCoreService).to.be.an('object');
204
+
205
+ tmpCoreService.magicBehavior('MAGICTESTDATA');
206
+ }
207
+ )
208
+ test
209
+ (
210
+ 'Construct a core service with a hash before Fable is initialized',
211
+ function()
212
+ {
213
+ let tmpCoreService = new MockCoreService({SomeOption: true}, 'MockCoreService-1');
214
+
215
+ Expect(tmpCoreService).to.be.an('object');
216
+ Expect(tmpCoreService.Hash).to.equal('MockCoreService-1');
217
+
218
+ tmpCoreService.magicBehavior('MAGICTESTDATA');
219
+ }
220
+ )
221
+
222
+ test
223
+ (
224
+ 'Construct a core service and attach it to Fable after Fable is initialized',
225
+ function()
226
+ {
227
+
228
+ let tmpCoreService = new MockCoreService({SomeOption: true}, 'MockCoreService-2');
229
+
230
+ Expect(tmpCoreService).to.be.an('object');
231
+ Expect(tmpCoreService.Hash).to.equal('MockCoreService-2');
232
+
233
+ let testFable = new libFable({});
234
+
235
+ testFable.serviceManager.connectPreinitServiceProviderInstance(tmpCoreService);
236
+
237
+ Expect(testFable.services.MockCoreService['MockCoreService-2']).to.be.an('object');
238
+ Expect(testFable.defaultServices.MockCoreService).to.be.an('object');
239
+
240
+ Expect(testFable.defaultServices.MockCoreService.fable.log).to.be.an('object');
241
+ }
242
+ )
243
+
244
+ test
245
+ (
246
+ 'Attempt to change the default service provider to a nonexistant provider',
247
+ function()
248
+ {
249
+ let testFable = new libFable({});
250
+
251
+ testFable.serviceManager.addServiceType('SimpleService', SimpleService);
252
+ testFable.serviceManager.addServiceType('DatabaseService', MockDatabaseService);
253
+
254
+ testFable.serviceManager.instantiateServiceProvider('SimpleService', {SomeOption: true});
255
+ testFable.serviceManager.defaultServices.SimpleService.doSomething();
256
+
257
+ testFable.serviceManager.instantiateServiceProvider('DatabaseService', {ConnectionString: 'mongodb://localhost:27017/test'}, 'PrimaryConnection');
258
+
259
+ Expect(testFable.serviceManager.defaultServices.DatabaseService.Hash).to.equal('PrimaryConnection');
260
+
261
+ testFable.serviceManager.instantiateServiceProvider('DatabaseService', {ConnectionString: 'mongodb://localhost:27017/test'}, 'SecondaryConnection');
262
+
263
+ Expect(testFable.serviceManager.defaultServices.DatabaseService.Hash).to.equal('PrimaryConnection');
264
+
265
+ testFable.serviceManager.defaultServices.DatabaseService.connect();
266
+ testFable.serviceManager.defaultServices.DatabaseService.commit('Test Record');
267
+
268
+ Expect(testFable.serviceManager.setDefaultServiceInstantiation('DatabaseService', 'TertiaryConnection')).to.be.false;
269
+
270
+ testFable.serviceManager.defaultServices.DatabaseService.connect();
271
+ testFable.serviceManager.defaultServices.DatabaseService.commit('Another Test Record');
272
+
273
+ Expect(testFable.serviceManager.defaultServices.DatabaseService.Hash).to.equal('PrimaryConnection');
274
+ }
275
+ );
276
+ }
277
+ );
278
+ }
279
+ );