fable-serviceproviderbase 3.0.16 → 3.0.18
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/CONTRIBUTING.md +50 -0
- package/README.md +195 -43
- package/docs/.nojekyll +0 -0
- package/docs/README.md +111 -0
- package/docs/_sidebar.md +15 -0
- package/docs/_topbar.md +5 -0
- package/docs/api.md +132 -0
- package/docs/cover.md +14 -0
- package/docs/css/docuserve.css +73 -0
- package/docs/index.html +39 -0
- package/docs/initialization-patterns.md +123 -0
- package/docs/retold-catalog.json +41 -0
- package/docs/retold-keyword-index.json +19 -0
- package/package.json +3 -3
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Contributing to Retold
|
|
2
|
+
|
|
3
|
+
We welcome contributions to Retold and its modules. This guide covers the expectations and process for contributing.
|
|
4
|
+
|
|
5
|
+
## Code of Conduct
|
|
6
|
+
|
|
7
|
+
The Retold community values **empathy**, **equity**, **kindness**, and **thoughtfulness**. We expect all participants to treat each other with respect, assume good intent, and engage constructively. These values apply to all interactions: pull requests, issues, discussions, and code review.
|
|
8
|
+
|
|
9
|
+
## How to Contribute
|
|
10
|
+
|
|
11
|
+
### Pull Requests
|
|
12
|
+
|
|
13
|
+
Pull requests are the preferred method for contributing changes. To submit one:
|
|
14
|
+
|
|
15
|
+
1. Fork the module repository you want to change
|
|
16
|
+
2. Create a branch for your work
|
|
17
|
+
3. Make your changes, following the code style of the module you are editing
|
|
18
|
+
4. Ensure your changes have test coverage (see below)
|
|
19
|
+
5. Open a pull request against the module's main branch
|
|
20
|
+
|
|
21
|
+
**Submitting a pull request does not guarantee it will be accepted.** Maintainers review contributions for fit, quality, and alignment with the project's direction. A PR may be declined, or you may be asked to revise it. This is normal and not a reflection on the quality of your effort.
|
|
22
|
+
|
|
23
|
+
### Reporting Issues
|
|
24
|
+
|
|
25
|
+
If you find a bug or have a feature suggestion, open an issue on the relevant module's repository. Include enough detail to reproduce the problem or understand the proposal.
|
|
26
|
+
|
|
27
|
+
## Test Coverage
|
|
28
|
+
|
|
29
|
+
Every commit must include test coverage for the changes it introduces. Retold modules use Mocha in TDD style. Before submitting:
|
|
30
|
+
|
|
31
|
+
- **Write tests** for any new functionality or bug fixes
|
|
32
|
+
- **Run the existing test suite** with `npm test` and confirm all tests pass
|
|
33
|
+
- **Check coverage** with `npm run coverage` if the module supports it
|
|
34
|
+
|
|
35
|
+
Pull requests that break existing tests or lack coverage for new code will not be merged.
|
|
36
|
+
|
|
37
|
+
## Code Style
|
|
38
|
+
|
|
39
|
+
Follow the conventions of the module you are working in. The general Retold style is:
|
|
40
|
+
|
|
41
|
+
- **Tabs** for indentation, never spaces
|
|
42
|
+
- **Plain JavaScript** only (no TypeScript)
|
|
43
|
+
- **Allman-style braces** (opening brace on its own line)
|
|
44
|
+
- **Variable naming:** `pVariable` for parameters, `tmpVariable` for temporaries, `libSomething` for imports
|
|
45
|
+
|
|
46
|
+
When in doubt, match what the surrounding code does.
|
|
47
|
+
|
|
48
|
+
## Repository Structure
|
|
49
|
+
|
|
50
|
+
Each module is its own git repository. The [retold](https://github.com/stevenvelozo/retold) repository tracks module organization but does not contain module source code. Direct your pull request to the specific module repository where your change belongs.
|
package/README.md
CHANGED
|
@@ -1,71 +1,223 @@
|
|
|
1
|
-
# Fable Service Provider
|
|
1
|
+
# Fable Service Provider Base
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
This is used for instantiating connections to databases, extending core
|
|
5
|
-
services and whatever other services.
|
|
3
|
+
The base class for all services in the Fable ecosystem. Provides a standard interface for dependency injection, options handling, unique identification, and lifecycle management — used to build database connectors, API servers, template engines, view controllers, and any other service that plugs into a Fable application.
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
[](https://github.com/stevenvelozo/fable-serviceproviderbase/actions)
|
|
6
|
+
[](https://badge.fury.io/js/fable-serviceproviderbase)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
* logging
|
|
11
|
-
* uuid
|
|
12
|
-
* templating
|
|
9
|
+
---
|
|
13
10
|
|
|
11
|
+
## Features
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
- **Service Base Class** - Standard constructor accepting a Fable instance, options object, and service hash
|
|
14
|
+
- **Dependency Injection** - Automatic access to `this.fable`, `this.log`, `this.services`, and `this.servicesMap` when connected to a Fable instance
|
|
15
|
+
- **Unique Identification** - Every service instance receives a UUID from Fable (or a random fallback) and a configurable Hash for service map lookups
|
|
16
|
+
- **Pre-Initialization Support** - Core services can be constructed before Fable is initialized and connected later via `connectFable()`
|
|
17
|
+
- **Standalone Mode** - Services can be instantiated without a Fable instance at all, receiving options and a random UUID
|
|
18
|
+
- **TypeScript Definitions** - Ships with `.d.ts` type declarations for editor support
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
class for most services. The constructor for this type takes in a fully
|
|
19
|
-
initialized fable object.
|
|
20
|
+
## Installation
|
|
20
21
|
|
|
22
|
+
```bash
|
|
23
|
+
npm install fable-serviceproviderbase
|
|
21
24
|
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```javascript
|
|
29
|
+
const libFable = require('fable');
|
|
22
30
|
const libFableServiceProviderBase = require('fable-serviceproviderbase');
|
|
23
31
|
|
|
24
|
-
class
|
|
32
|
+
class GreeterService extends libFableServiceProviderBase
|
|
25
33
|
{
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
34
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
35
|
+
{
|
|
36
|
+
super(pFable, pOptions, pServiceHash);
|
|
29
37
|
|
|
30
|
-
|
|
31
|
-
|
|
38
|
+
this.serviceType = 'GreeterService';
|
|
39
|
+
}
|
|
32
40
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
greet(pName)
|
|
42
|
+
{
|
|
43
|
+
this.log.info(`Hello, ${pName}! I am service ${this.Hash}.`);
|
|
44
|
+
}
|
|
37
45
|
}
|
|
38
|
-
```
|
|
39
46
|
|
|
40
|
-
|
|
47
|
+
let fable = new libFable();
|
|
41
48
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
fable.serviceManager.addServiceType('GreeterService', GreeterService);
|
|
50
|
+
fable.serviceManager.instantiateServiceProvider('GreeterService',
|
|
51
|
+
{ greeting: 'Hello' }, 'PrimaryGreeter');
|
|
45
52
|
|
|
46
|
-
|
|
47
|
-
|
|
53
|
+
fable.services.GreeterService.greet('World');
|
|
54
|
+
```
|
|
48
55
|
|
|
49
|
-
|
|
50
|
-
manager code as well to get a good understanding of how initialization
|
|
51
|
-
differs from the basic services.
|
|
56
|
+
## Usage
|
|
52
57
|
|
|
58
|
+
### Basic Services
|
|
53
59
|
|
|
54
|
-
|
|
60
|
+
Most services extend the base class directly and receive a fully initialized Fable instance:
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
55
63
|
const libFableServiceProviderBase = require('fable-serviceproviderbase');
|
|
56
64
|
|
|
57
65
|
class SimpleService extends libFableServiceProviderBase
|
|
58
66
|
{
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
67
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
68
|
+
{
|
|
69
|
+
super(pFable, pOptions, pServiceHash);
|
|
62
70
|
|
|
63
|
-
|
|
64
|
-
|
|
71
|
+
this.serviceType = 'SimpleService';
|
|
72
|
+
}
|
|
65
73
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
74
|
+
doSomething()
|
|
75
|
+
{
|
|
76
|
+
this.fable.log.info(`SimpleService ${this.UUID}::${this.Hash} is doing something.`);
|
|
77
|
+
}
|
|
70
78
|
}
|
|
71
79
|
```
|
|
80
|
+
|
|
81
|
+
Register and use through the Fable service manager:
|
|
82
|
+
|
|
83
|
+
```javascript
|
|
84
|
+
let fable = new libFable();
|
|
85
|
+
|
|
86
|
+
fable.serviceManager.addServiceType('SimpleService', SimpleService);
|
|
87
|
+
fable.serviceManager.instantiateServiceProvider('SimpleService',
|
|
88
|
+
{ SomeOption: true }, 'SimpleService-123');
|
|
89
|
+
|
|
90
|
+
// Access via the services map
|
|
91
|
+
fable.services.SimpleService.doSomething();
|
|
92
|
+
|
|
93
|
+
// Or look up a specific instance by hash
|
|
94
|
+
fable.servicesMap.SimpleService['SimpleService-123'].doSomething();
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Core Pre-Initialization Services
|
|
98
|
+
|
|
99
|
+
Some services need to exist before Fable is fully initialized (e.g., logging, settings, UUID generation). These use the `CoreServiceProviderBase` export and connect to Fable later:
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
const libCoreServiceBase = require('fable-serviceproviderbase').CoreServiceProviderBase;
|
|
103
|
+
|
|
104
|
+
class EarlyService extends libCoreServiceBase
|
|
105
|
+
{
|
|
106
|
+
constructor(pOptions, pServiceHash)
|
|
107
|
+
{
|
|
108
|
+
super(pOptions, pServiceHash);
|
|
109
|
+
|
|
110
|
+
this.serviceType = 'EarlyService';
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
earlyWork()
|
|
114
|
+
{
|
|
115
|
+
console.log(`EarlyService ${this.UUID}::${this.Hash} is working.`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Create before Fable exists
|
|
120
|
+
let earlyService = new EarlyService({ SomeOption: true }, 'EarlyService-1');
|
|
121
|
+
earlyService.earlyWork();
|
|
122
|
+
|
|
123
|
+
// Later, connect to Fable
|
|
124
|
+
let fable = new libFable();
|
|
125
|
+
fable.serviceManager.connectPreinitServiceProviderInstance(earlyService);
|
|
126
|
+
|
|
127
|
+
// Now it has full fable access
|
|
128
|
+
earlyService.fable.log.info('Connected to Fable!');
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Standalone Mode
|
|
132
|
+
|
|
133
|
+
Services can be instantiated without any Fable instance. They receive a random UUID and the first parameter is treated as the options object:
|
|
134
|
+
|
|
135
|
+
```javascript
|
|
136
|
+
let standalone = new SimpleService({ Setting: 'Something' });
|
|
137
|
+
// standalone.options.Setting === 'Something'
|
|
138
|
+
// standalone.UUID is a random string like 'CORE-SVC-12345'
|
|
139
|
+
// standalone.fable === false
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## API
|
|
143
|
+
|
|
144
|
+
### Constructor
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
new FableServiceProviderBase(pFable, pOptions, pServiceHash)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
| Parameter | Type | Description |
|
|
151
|
+
|-----------|------|-------------|
|
|
152
|
+
| `pFable` | `Fable \| Object` | A Fable instance, or an options object if no Fable is available |
|
|
153
|
+
| `pOptions` | `Object \| String` | Options object, or service hash string if no Fable is available |
|
|
154
|
+
| `pServiceHash` | `String` | Identifier for this service instance in the services map |
|
|
155
|
+
|
|
156
|
+
### Methods
|
|
157
|
+
|
|
158
|
+
| Method | Description |
|
|
159
|
+
|--------|-------------|
|
|
160
|
+
| `connectFable(pFable)` | Attach a Fable instance after construction. Sets `this.fable`, `this.log`, `this.services`, and `this.servicesMap`. Returns `true` on success or an `Error` on failure. |
|
|
161
|
+
|
|
162
|
+
### Properties
|
|
163
|
+
|
|
164
|
+
| Property | Type | Description |
|
|
165
|
+
|----------|------|-------------|
|
|
166
|
+
| `fable` | `Fable \| false` | The connected Fable instance, or `false` if standalone |
|
|
167
|
+
| `UUID` | `String` | Unique identifier assigned by Fable or generated randomly |
|
|
168
|
+
| `Hash` | `String` | Service hash for lookups in the services map (defaults to UUID) |
|
|
169
|
+
| `serviceType` | `String` | Service type identifier (set by the deriving class) |
|
|
170
|
+
| `options` | `Object` | Options object passed at construction |
|
|
171
|
+
| `log` | `Object` | Reference to `fable.Logging` (available after Fable connection) |
|
|
172
|
+
| `services` | `Object` | Reference to `fable.services` (available after Fable connection) |
|
|
173
|
+
| `servicesMap` | `Object` | Reference to `fable.servicesMap` (available after Fable connection) |
|
|
174
|
+
|
|
175
|
+
### Static Properties
|
|
176
|
+
|
|
177
|
+
| Property | Type | Description |
|
|
178
|
+
|----------|------|-------------|
|
|
179
|
+
| `isFableService` | `Boolean` | Always `true` — used to identify Fable service classes |
|
|
180
|
+
|
|
181
|
+
### Exports
|
|
182
|
+
|
|
183
|
+
| Export | Description |
|
|
184
|
+
|--------|-------------|
|
|
185
|
+
| `require('fable-serviceproviderbase')` | The `FableServiceProviderBase` class |
|
|
186
|
+
| `require('fable-serviceproviderbase').CoreServiceProviderBase` | Same class (alias for pre-init service pattern) |
|
|
187
|
+
|
|
188
|
+
## Part of the Retold Framework
|
|
189
|
+
|
|
190
|
+
Fable Service Provider Base is the foundation class for all services in the ecosystem:
|
|
191
|
+
|
|
192
|
+
- [fable](https://github.com/stevenvelozo/fable) - Application services framework and service manager
|
|
193
|
+
- [fable-log](https://github.com/stevenvelozo/fable-log) - Logging framework (core service)
|
|
194
|
+
- [fable-uuid](https://github.com/stevenvelozo/fable-uuid) - UUID generation (core service)
|
|
195
|
+
- [meadow](https://github.com/stevenvelozo/meadow) - ORM built as Fable services
|
|
196
|
+
- [orator](https://github.com/stevenvelozo/orator) - API server built as Fable services
|
|
197
|
+
- [pict](https://github.com/stevenvelozo/pict) - MVC framework built as Fable services
|
|
198
|
+
|
|
199
|
+
## Testing
|
|
200
|
+
|
|
201
|
+
Run the test suite:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
npm test
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Run with coverage:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
npm run coverage
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Related Packages
|
|
214
|
+
|
|
215
|
+
- [fable](https://github.com/stevenvelozo/fable) - Application services framework
|
|
216
|
+
|
|
217
|
+
## License
|
|
218
|
+
|
|
219
|
+
MIT
|
|
220
|
+
|
|
221
|
+
## Contributing
|
|
222
|
+
|
|
223
|
+
Pull requests are welcome. For details on our code of conduct, contribution process, and testing requirements, see the [Retold Contributing Guide](https://github.com/stevenvelozo/retold/blob/main/docs/contributing.md).
|
package/docs/.nojekyll
ADDED
|
File without changes
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Fable Service Provider Base
|
|
2
|
+
|
|
3
|
+
The base class that every Retold service extends. It provides the contract for registration, dependency injection, and lifecycle management within a Fable instance.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
When you extend `FableServiceProviderBase`, your class gains:
|
|
8
|
+
|
|
9
|
+
- `this.fable` -- Reference to the Fable instance (or `false` if standalone)
|
|
10
|
+
- `this.log` -- Shortcut to Fable's logging service
|
|
11
|
+
- `this.services` -- Access to all registered services
|
|
12
|
+
- `this.servicesMap` -- The full service registry map
|
|
13
|
+
- `this.options` -- Service-specific configuration
|
|
14
|
+
- `this.serviceType` -- The registered type name (set this in your constructor)
|
|
15
|
+
- `this.Hash` -- Unique identifier for this specific instance
|
|
16
|
+
- `this.UUID` -- Auto-generated unique ID
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```javascript
|
|
21
|
+
const libFableServiceProviderBase = require('fable-serviceproviderbase');
|
|
22
|
+
|
|
23
|
+
class MyService extends libFableServiceProviderBase
|
|
24
|
+
{
|
|
25
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
26
|
+
{
|
|
27
|
+
super(pFable, pOptions, pServiceHash);
|
|
28
|
+
this.serviceType = 'MyService';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
doSomething()
|
|
32
|
+
{
|
|
33
|
+
this.log.info('MyService is doing something');
|
|
34
|
+
return this.fable.getUUID();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Register with a Fable instance:
|
|
40
|
+
|
|
41
|
+
```javascript
|
|
42
|
+
const libFable = require('fable');
|
|
43
|
+
let _Fable = new libFable();
|
|
44
|
+
|
|
45
|
+
// Register the type and create an instance
|
|
46
|
+
_Fable.serviceManager.addServiceType('MyService', MyService);
|
|
47
|
+
_Fable.serviceManager.instantiateServiceProvider('MyService', { SomeOption: true }, 'MyService-1');
|
|
48
|
+
|
|
49
|
+
// Access via the services shortcut
|
|
50
|
+
_Fable.services.MyService.doSomething();
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Or use the shorthand:
|
|
54
|
+
|
|
55
|
+
```javascript
|
|
56
|
+
_Fable.addAndInstantiateServiceType('MyService', MyService);
|
|
57
|
+
_Fable.services.MyService.doSomething();
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Three Initialization Patterns
|
|
61
|
+
|
|
62
|
+
The constructor is flexible and supports three modes. See [Initialization Patterns](initialization-patterns.md) for details.
|
|
63
|
+
|
|
64
|
+
**With Fable** -- The standard pattern for application services:
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
let tmpService = new MyService(fableInstance, optionsObject, serviceHash);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Pre-initialization** -- For core services needed before Fable is ready:
|
|
71
|
+
|
|
72
|
+
```javascript
|
|
73
|
+
let tmpCore = new MyCoreService(optionsObject, serviceHash);
|
|
74
|
+
// Later, after Fable is ready:
|
|
75
|
+
fableInstance.serviceManager.connectPreinitServiceProviderInstance(tmpCore);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Standalone** -- For testing or non-Fable contexts:
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
let tmpService = new MyService({ Setting: 'value' });
|
|
82
|
+
// tmpService.fable === false
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Multiple Instances
|
|
86
|
+
|
|
87
|
+
You can create multiple instances of the same service type, each with a different hash:
|
|
88
|
+
|
|
89
|
+
```javascript
|
|
90
|
+
_Fable.serviceManager.instantiateServiceProvider('DatabaseService', { Host: 'primary-db' }, 'Primary');
|
|
91
|
+
_Fable.serviceManager.instantiateServiceProvider('DatabaseService', { Host: 'replica-db' }, 'Replica');
|
|
92
|
+
|
|
93
|
+
// Access the default (first registered)
|
|
94
|
+
_Fable.services.DatabaseService.connect();
|
|
95
|
+
|
|
96
|
+
// Access a specific instance
|
|
97
|
+
_Fable.servicesMap.DatabaseService['Replica'].connect();
|
|
98
|
+
|
|
99
|
+
// Change the default
|
|
100
|
+
_Fable.serviceManager.setDefaultServiceInstantiation('DatabaseService', 'Replica');
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## API Reference
|
|
104
|
+
|
|
105
|
+
See the [API Reference](api.md) for complete method and property documentation.
|
|
106
|
+
|
|
107
|
+
## Learn More
|
|
108
|
+
|
|
109
|
+
- [Initialization Patterns](initialization-patterns.md) -- The three ways to construct a service
|
|
110
|
+
- [API Reference](api.md) -- Properties, methods, and static members
|
|
111
|
+
- [Fable Service Provider Pattern](/fable/fable/) -- How services compose in the Fable ecosystem
|
package/docs/_sidebar.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
- Getting Started
|
|
2
|
+
|
|
3
|
+
- [Overview](README.md)
|
|
4
|
+
- [Initialization Patterns](initialization-patterns.md)
|
|
5
|
+
|
|
6
|
+
- Reference
|
|
7
|
+
|
|
8
|
+
- [API Reference](api.md)
|
|
9
|
+
|
|
10
|
+
- Retold Ecosystem
|
|
11
|
+
|
|
12
|
+
- [Fable](/fable/fable/)
|
|
13
|
+
- [Fable-Settings](/fable/fable-settings/)
|
|
14
|
+
- [Fable-Log](/fable/fable-log/)
|
|
15
|
+
- [Fable-UUID](/fable/fable-uuid/)
|
package/docs/_topbar.md
ADDED
package/docs/api.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
## Class: FableServiceProviderBase
|
|
4
|
+
|
|
5
|
+
The base class for all Fable services. Import it and extend it to create your own services.
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
const libFableServiceProviderBase = require('fable-serviceproviderbase');
|
|
9
|
+
|
|
10
|
+
class MyService extends libFableServiceProviderBase
|
|
11
|
+
{
|
|
12
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
13
|
+
{
|
|
14
|
+
super(pFable, pOptions, pServiceHash);
|
|
15
|
+
this.serviceType = 'MyService';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Constructor
|
|
21
|
+
|
|
22
|
+
```javascript
|
|
23
|
+
new FableServiceProviderBase(pFable, pOptions, pServiceHash)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
| Parameter | Type | Required | Description |
|
|
27
|
+
|-----------|------|----------|-------------|
|
|
28
|
+
| `pFable` | Fable instance or object | No | A Fable instance, or an options object if no Fable is available |
|
|
29
|
+
| `pOptions` | object or string | No | Options for the service, or the service hash if no Fable |
|
|
30
|
+
| `pServiceHash` | string | No | Unique identifier for this service instance |
|
|
31
|
+
|
|
32
|
+
See [Initialization Patterns](initialization-patterns.md) for detailed usage of each parameter combination.
|
|
33
|
+
|
|
34
|
+
## Instance Properties
|
|
35
|
+
|
|
36
|
+
### fable
|
|
37
|
+
|
|
38
|
+
- **Type:** Fable instance or `false`
|
|
39
|
+
- **Description:** Reference to the connected Fable instance. Set to `false` when no Fable is connected.
|
|
40
|
+
|
|
41
|
+
### log
|
|
42
|
+
|
|
43
|
+
- **Type:** object or `undefined`
|
|
44
|
+
- **Description:** Shortcut to `fable.Logging`. Provides `trace()`, `debug()`, `info()`, `warn()`, `error()`, and `fatal()` methods.
|
|
45
|
+
|
|
46
|
+
### UUID
|
|
47
|
+
|
|
48
|
+
- **Type:** string
|
|
49
|
+
- **Description:** Unique identifier for this service instance. Generated by Fable's UUID service when connected, or a random `CORE-SVC-XXXXX` string when standalone.
|
|
50
|
+
|
|
51
|
+
### Hash
|
|
52
|
+
|
|
53
|
+
- **Type:** string
|
|
54
|
+
- **Description:** The service instance hash, used to look up this specific instance in the service registry. Defaults to the UUID if not provided.
|
|
55
|
+
|
|
56
|
+
### serviceType
|
|
57
|
+
|
|
58
|
+
- **Type:** string
|
|
59
|
+
- **Description:** The registered type name for this service. Defaults to `'Unknown-{UUID}'`. Subclasses should set this in their constructor.
|
|
60
|
+
|
|
61
|
+
### options
|
|
62
|
+
|
|
63
|
+
- **Type:** object
|
|
64
|
+
- **Description:** Service-specific configuration passed during construction.
|
|
65
|
+
|
|
66
|
+
### services
|
|
67
|
+
|
|
68
|
+
- **Type:** object or `undefined`
|
|
69
|
+
- **Description:** Reference to `fable.services`. Provides shortcut access to the default instance of each registered service type.
|
|
70
|
+
|
|
71
|
+
### servicesMap
|
|
72
|
+
|
|
73
|
+
- **Type:** object or `undefined`
|
|
74
|
+
- **Description:** Reference to `fable.servicesMap`. A two-level map: `servicesMap[serviceType][hash]` returns a specific service instance.
|
|
75
|
+
|
|
76
|
+
### _PackageFableServiceProvider
|
|
77
|
+
|
|
78
|
+
- **Type:** object
|
|
79
|
+
- **Description:** The `package.json` contents of fable-serviceproviderbase. Useful for version checking.
|
|
80
|
+
|
|
81
|
+
## Instance Methods
|
|
82
|
+
|
|
83
|
+
### connectFable(pFable)
|
|
84
|
+
|
|
85
|
+
Connects a Fable instance to this service. Used for core services that were constructed before Fable was initialized.
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
let tmpResult = myService.connectFable(fableInstance);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
| Parameter | Type | Required | Description |
|
|
92
|
+
|-----------|------|----------|-------------|
|
|
93
|
+
| `pFable` | Fable instance | Yes | Must have `isFable` property set to `true` |
|
|
94
|
+
|
|
95
|
+
**Returns:** `true` on success, or an `Error` if the parameter is not a valid Fable instance.
|
|
96
|
+
|
|
97
|
+
**Behavior:**
|
|
98
|
+
- Sets `this.fable` if not already set
|
|
99
|
+
- Sets `this.log` to `fable.Logging` if not already set
|
|
100
|
+
- Sets `this.services` to `fable.services` if not already set
|
|
101
|
+
- Sets `this.servicesMap` to `fable.servicesMap` if not already set
|
|
102
|
+
- Idempotent: calling multiple times will not overwrite existing references
|
|
103
|
+
|
|
104
|
+
## Static Properties
|
|
105
|
+
|
|
106
|
+
### isFableService
|
|
107
|
+
|
|
108
|
+
- **Type:** boolean
|
|
109
|
+
- **Value:** `true`
|
|
110
|
+
- **Description:** Class-level flag that identifies a class as a Fable service. Used by the service manager to validate service types.
|
|
111
|
+
|
|
112
|
+
## Exports
|
|
113
|
+
|
|
114
|
+
### Default Export
|
|
115
|
+
|
|
116
|
+
The `FableServiceProviderBase` class itself.
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
const libBase = require('fable-serviceproviderbase');
|
|
120
|
+
class MyService extends libBase { ... }
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### CoreServiceProviderBase
|
|
124
|
+
|
|
125
|
+
An alias for `FableServiceProviderBase`. They are the same class.
|
|
126
|
+
|
|
127
|
+
```javascript
|
|
128
|
+
const libBase = require('fable-serviceproviderbase');
|
|
129
|
+
class MyCoreService extends libBase.CoreServiceProviderBase { ... }
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The alias exists for readability when building services that are designed to be constructed before Fable is initialized.
|
package/docs/cover.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Fable Service Provider Base
|
|
2
|
+
|
|
3
|
+
> The foundation class for every Retold service
|
|
4
|
+
|
|
5
|
+
A lightweight base class that provides registration, dependency injection, and lifecycle management. Every service in the Fable ecosystem -- from logging to data access to views -- extends this class.
|
|
6
|
+
|
|
7
|
+
- **Dependency Injection** -- Access logging, configuration, and other services through `this.fable`
|
|
8
|
+
- **Service Registry** -- Register by type, instantiate with unique hashes, discover via `this.services`
|
|
9
|
+
- **Flexible Initialization** -- Construct with Fable, before Fable, or without Fable at all
|
|
10
|
+
- **Multiple Instances** -- Run several instances of the same service type with different configurations
|
|
11
|
+
|
|
12
|
+
[Get Started](README.md)
|
|
13
|
+
[API Reference](api.md)
|
|
14
|
+
[GitHub](https://github.com/stevenvelozo/fable-serviceproviderbase)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
Pict Docuserve - Base Styles
|
|
3
|
+
============================================================================ */
|
|
4
|
+
|
|
5
|
+
/* Reset and base */
|
|
6
|
+
*, *::before, *::after {
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
html, body {
|
|
11
|
+
margin: 0;
|
|
12
|
+
padding: 0;
|
|
13
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
14
|
+
font-size: 16px;
|
|
15
|
+
line-height: 1.5;
|
|
16
|
+
color: #423D37;
|
|
17
|
+
background-color: #fff;
|
|
18
|
+
-webkit-font-smoothing: antialiased;
|
|
19
|
+
-moz-osx-font-smoothing: grayscale;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* Typography */
|
|
23
|
+
h1, h2, h3, h4, h5, h6 {
|
|
24
|
+
margin-top: 0;
|
|
25
|
+
line-height: 1.3;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
a {
|
|
29
|
+
color: #2E7D74;
|
|
30
|
+
text-decoration: none;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
a:hover {
|
|
34
|
+
color: #256861;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* Application container */
|
|
38
|
+
#Docuserve-Application-Container {
|
|
39
|
+
min-height: 100vh;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* Utility: scrollbar styling */
|
|
43
|
+
::-webkit-scrollbar {
|
|
44
|
+
width: 8px;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
::-webkit-scrollbar-track {
|
|
48
|
+
background: #F5F0E8;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
::-webkit-scrollbar-thumb {
|
|
52
|
+
background: #D4CCBE;
|
|
53
|
+
border-radius: 4px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
::-webkit-scrollbar-thumb:hover {
|
|
57
|
+
background: #B5AA9A;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Responsive adjustments */
|
|
61
|
+
@media (max-width: 768px) {
|
|
62
|
+
html {
|
|
63
|
+
font-size: 14px;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
#Docuserve-Sidebar-Container {
|
|
67
|
+
display: none;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.docuserve-body {
|
|
71
|
+
flex-direction: column;
|
|
72
|
+
}
|
|
73
|
+
}
|
package/docs/index.html
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
7
|
+
<meta name="description" content="Documentation powered by pict-docuserve">
|
|
8
|
+
|
|
9
|
+
<title>Documentation</title>
|
|
10
|
+
|
|
11
|
+
<!-- Application Stylesheet -->
|
|
12
|
+
<link href="css/docuserve.css" rel="stylesheet">
|
|
13
|
+
<!-- KaTeX stylesheet for LaTeX equation rendering -->
|
|
14
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.css">
|
|
15
|
+
<!-- PICT Dynamic View CSS Container -->
|
|
16
|
+
<style id="PICT-CSS"></style>
|
|
17
|
+
|
|
18
|
+
<!-- Load the PICT library from jsDelivr CDN -->
|
|
19
|
+
<script src="https://cdn.jsdelivr.net/npm/pict@1/dist/pict.min.js" type="text/javascript"></script>
|
|
20
|
+
<!-- Bootstrap the Application -->
|
|
21
|
+
<script type="text/javascript">
|
|
22
|
+
//<![CDATA[
|
|
23
|
+
Pict.safeOnDocumentReady(() => { Pict.safeLoadPictApplication(PictDocuserve, 2)});
|
|
24
|
+
//]]>
|
|
25
|
+
</script>
|
|
26
|
+
</head>
|
|
27
|
+
<body>
|
|
28
|
+
<!-- The root container for the Pict application -->
|
|
29
|
+
<div id="Docuserve-Application-Container"></div>
|
|
30
|
+
|
|
31
|
+
<!-- Mermaid diagram rendering -->
|
|
32
|
+
<script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
|
|
33
|
+
<script>mermaid.initialize({ startOnLoad: false, theme: 'default' });</script>
|
|
34
|
+
<!-- KaTeX for LaTeX equation rendering -->
|
|
35
|
+
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.js"></script>
|
|
36
|
+
<!-- Load the Docuserve PICT Application Bundle from jsDelivr CDN -->
|
|
37
|
+
<script src="https://cdn.jsdelivr.net/npm/pict-docuserve@0/dist/pict-docuserve.min.js" type="text/javascript"></script>
|
|
38
|
+
</body>
|
|
39
|
+
</html>
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Initialization Patterns
|
|
2
|
+
|
|
3
|
+
The `FableServiceProviderBase` constructor supports three initialization modes. The same base class handles all three -- it detects whether a Fable instance was passed in and adjusts behavior accordingly.
|
|
4
|
+
|
|
5
|
+
## Pattern 1: With Fable
|
|
6
|
+
|
|
7
|
+
The standard pattern for application services. Pass a Fable instance as the first argument.
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
const libFableServiceProviderBase = require('fable-serviceproviderbase');
|
|
11
|
+
|
|
12
|
+
class MyService extends libFableServiceProviderBase
|
|
13
|
+
{
|
|
14
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
15
|
+
{
|
|
16
|
+
super(pFable, pOptions, pServiceHash);
|
|
17
|
+
this.serviceType = 'MyService';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const libFable = require('fable');
|
|
22
|
+
let _Fable = new libFable();
|
|
23
|
+
|
|
24
|
+
let tmpService = new MyService(_Fable, { ConnectionTimeout: 5000 }, 'Primary');
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
After construction:
|
|
28
|
+
|
|
29
|
+
| Property | Value |
|
|
30
|
+
|----------|-------|
|
|
31
|
+
| `this.fable` | The Fable instance |
|
|
32
|
+
| `this.log` | `fable.Logging` |
|
|
33
|
+
| `this.services` | `fable.services` |
|
|
34
|
+
| `this.servicesMap` | `fable.servicesMap` |
|
|
35
|
+
| `this.UUID` | Generated by Fable's UUID service |
|
|
36
|
+
| `this.options` | `{ ConnectionTimeout: 5000 }` |
|
|
37
|
+
| `this.Hash` | `'Primary'` |
|
|
38
|
+
|
|
39
|
+
## Pattern 2: Pre-initialization (Core Services)
|
|
40
|
+
|
|
41
|
+
Some services need to exist before Fable is fully initialized -- for example, logging or settings services that Fable itself depends on. These are constructed without a Fable instance and connected later.
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
const libFableServiceProviderBase = require('fable-serviceproviderbase');
|
|
45
|
+
|
|
46
|
+
class MyCoreService extends libFableServiceProviderBase.CoreServiceProviderBase
|
|
47
|
+
{
|
|
48
|
+
constructor(pOptions, pServiceHash)
|
|
49
|
+
{
|
|
50
|
+
super(pOptions, pServiceHash);
|
|
51
|
+
this.serviceType = 'MyCoreService';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
earlyBehavior()
|
|
55
|
+
{
|
|
56
|
+
// This works even before Fable is initialized
|
|
57
|
+
console.log(`Core service ${this.Hash} is ready`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Create the service early
|
|
62
|
+
let tmpCore = new MyCoreService({ SomeOption: true }, 'CoreInstance-1');
|
|
63
|
+
tmpCore.earlyBehavior();
|
|
64
|
+
|
|
65
|
+
// Later, when Fable is ready, connect it
|
|
66
|
+
let _Fable = new libFable();
|
|
67
|
+
_Fable.serviceManager.connectPreinitServiceProviderInstance(tmpCore);
|
|
68
|
+
|
|
69
|
+
// Now tmpCore.fable, tmpCore.log, tmpCore.services are all available
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
After construction (before `connectFable`):
|
|
73
|
+
|
|
74
|
+
| Property | Value |
|
|
75
|
+
|----------|-------|
|
|
76
|
+
| `this.fable` | `false` |
|
|
77
|
+
| `this.log` | `undefined` |
|
|
78
|
+
| `this.services` | `undefined` |
|
|
79
|
+
| `this.UUID` | `'CORE-SVC-XXXXX'` (random 5-digit number) |
|
|
80
|
+
| `this.options` | `{ SomeOption: true }` |
|
|
81
|
+
| `this.Hash` | `'CoreInstance-1'` |
|
|
82
|
+
|
|
83
|
+
After `connectFable` or `connectPreinitServiceProviderInstance`:
|
|
84
|
+
|
|
85
|
+
| Property | Value |
|
|
86
|
+
|----------|-------|
|
|
87
|
+
| `this.fable` | The Fable instance |
|
|
88
|
+
| `this.log` | `fable.Logging` |
|
|
89
|
+
| `this.services` | `fable.services` |
|
|
90
|
+
|
|
91
|
+
Note: `CoreServiceProviderBase` is an alias for `FableServiceProviderBase`. They are the same class. The alias exists for readability -- it signals that the service is designed for pre-initialization use.
|
|
92
|
+
|
|
93
|
+
## Pattern 3: Standalone (No Fable)
|
|
94
|
+
|
|
95
|
+
For testing or non-Fable contexts, services can be constructed with just an options object:
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
let tmpService = new MyService({ Setting: 'value' });
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
After construction:
|
|
102
|
+
|
|
103
|
+
| Property | Value |
|
|
104
|
+
|----------|-------|
|
|
105
|
+
| `this.fable` | `false` |
|
|
106
|
+
| `this.log` | `undefined` |
|
|
107
|
+
| `this.UUID` | `'CORE-SVC-XXXXX'` (random) |
|
|
108
|
+
| `this.options` | `{ Setting: 'value' }` |
|
|
109
|
+
| `this.Hash` | Same as UUID |
|
|
110
|
+
|
|
111
|
+
The service works but has no access to Fable's logging, configuration, or other services. You can call `connectFable(fableInstance)` later to wire everything up.
|
|
112
|
+
|
|
113
|
+
## Constructor Parameter Detection
|
|
114
|
+
|
|
115
|
+
The constructor uses a simple heuristic: if the first parameter is an object with an `isFable` property set to `true`, it treats it as a Fable instance. Otherwise, the first parameter is treated as the options object.
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
new Service(fable, options, hash) → fable.isFable is true → Pattern 1
|
|
119
|
+
new Service(options, hash) → options.isFable is falsy → Pattern 2/3
|
|
120
|
+
new Service() → no arguments → Pattern 3
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The `pServiceHash` parameter sets `this.Hash`. If omitted, the hash defaults to the UUID. When no Fable is present, if the second parameter is a string, it is used as the hash.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Generated": "2026-02-18T03:21:49.210Z",
|
|
3
|
+
"GitHubOrg": "stevenvelozo",
|
|
4
|
+
"DefaultBranch": "master",
|
|
5
|
+
"Groups": [
|
|
6
|
+
{
|
|
7
|
+
"Name": "Dist",
|
|
8
|
+
"Key": "dist",
|
|
9
|
+
"Description": "",
|
|
10
|
+
"Modules": [
|
|
11
|
+
{
|
|
12
|
+
"Name": "indoctrinate_content_staging",
|
|
13
|
+
"Repo": "indoctrinate_content_staging",
|
|
14
|
+
"Group": "dist",
|
|
15
|
+
"Branch": "master",
|
|
16
|
+
"HasDocs": false,
|
|
17
|
+
"HasCover": false,
|
|
18
|
+
"Sidebar": [],
|
|
19
|
+
"DocFiles": []
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"Name": "Types",
|
|
25
|
+
"Key": "types",
|
|
26
|
+
"Description": "",
|
|
27
|
+
"Modules": [
|
|
28
|
+
{
|
|
29
|
+
"Name": "source",
|
|
30
|
+
"Repo": "source",
|
|
31
|
+
"Group": "types",
|
|
32
|
+
"Branch": "master",
|
|
33
|
+
"HasDocs": false,
|
|
34
|
+
"HasCover": false,
|
|
35
|
+
"Sidebar": [],
|
|
36
|
+
"DocFiles": []
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Generated": "2026-02-18T03:21:49.288Z",
|
|
3
|
+
"DocumentCount": 0,
|
|
4
|
+
"LunrIndex": {
|
|
5
|
+
"version": "2.3.9",
|
|
6
|
+
"fields": [
|
|
7
|
+
"title",
|
|
8
|
+
"module",
|
|
9
|
+
"group",
|
|
10
|
+
"body"
|
|
11
|
+
],
|
|
12
|
+
"fieldVectors": [],
|
|
13
|
+
"invertedIndex": [],
|
|
14
|
+
"pipeline": [
|
|
15
|
+
"stemmer"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
"Documents": {}
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fable-serviceproviderbase",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.18",
|
|
4
4
|
"description": "Simple base classes for fable services.",
|
|
5
5
|
"main": "source/Fable-ServiceProviderBase.js",
|
|
6
6
|
"scripts": {
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"homepage": "https://github.com/stevenvelozo/fable-serviceproviderbase",
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/mocha": "^10.0.10",
|
|
50
|
-
"fable": "^3.1.
|
|
51
|
-
"quackage": "^1.0.
|
|
50
|
+
"fable": "^3.1.55",
|
|
51
|
+
"quackage": "^1.0.51",
|
|
52
52
|
"typescript": "^5.9.3"
|
|
53
53
|
}
|
|
54
54
|
}
|