orator 5.0.1 → 5.0.2
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 +58 -81
- package/docs/.nojekyll +0 -0
- package/docs/README.md +142 -0
- package/docs/_sidebar.md +21 -0
- package/docs/architecture.md +92 -0
- package/docs/configuration.md +94 -0
- package/docs/cover.md +11 -0
- package/docs/getting-started.md +133 -0
- package/docs/http-proxy.md +45 -0
- package/docs/index.html +51 -0
- package/docs/ipc-server.md +123 -0
- package/docs/lifecycle-hooks.md +95 -0
- package/docs/restify-server.md +82 -0
- package/docs/service-servers.md +87 -0
- package/docs/static-files.md +75 -0
- package/package.json +3 -3
- package/source/Orator.js +27 -2
- package/test/Orator_complex_routes_tests.js +949 -0
- package/test/Orator_static_serving_tests.js +1322 -0
- package/test/static_content/about.html +1 -0
- package/test/static_content/data.json +1 -0
- package/test/static_content/index.html +1 -0
- package/test/static_content/style.css +1 -0
- package/test/static_content/subsite/index.html +1 -0
package/README.md
CHANGED
|
@@ -1,107 +1,84 @@
|
|
|
1
1
|
# Orator
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> An unopinionated API server abstraction for REST and IPC services
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Orator is not an attempt to reinvent the wheel. Nor do we want to make a car with five of them. Orator is a thin abstraction layer over service server implementations (like Restify), providing a consistent interface for building API servers. You can spin up a web server in a single simple line, and configuration is managed through a consistent JSON format -- so as you begin to have 10 or 15 or 5,000 microservices, you don't have a bunch of boilerplate API server code laying around.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Features
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- **Unopinionated Design** - Wraps any service server implementation through a consistent interface
|
|
10
|
+
- **REST and IPC** - Full HTTP server support via Restify, or in-process IPC for testing and microservice composition
|
|
11
|
+
- **Lifecycle Management** - Before/After hooks for initialization and service start phases
|
|
12
|
+
- **Static File Serving** - Built-in static file serving with subdomain-based folder routing
|
|
13
|
+
- **Fable Integration** - First-class service provider in the Fable ecosystem with logging and configuration
|
|
14
|
+
- **Browser & Node.js** - Works in both environments with automatic service server selection
|
|
10
15
|
|
|
11
|
-
##
|
|
16
|
+
## Quick Start
|
|
12
17
|
|
|
13
|
-
|
|
18
|
+
```javascript
|
|
19
|
+
const libFable = require('fable');
|
|
20
|
+
const libOrator = require('orator');
|
|
21
|
+
const libOratorServiceServerRestify = require('orator-serviceserver-restify');
|
|
14
22
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
const _Fable = new libFable({
|
|
24
|
+
Product: 'MyAPIServer',
|
|
25
|
+
ProductVersion: '1.0.0',
|
|
26
|
+
ServicePort: 8080
|
|
27
|
+
});
|
|
18
28
|
|
|
19
|
-
|
|
29
|
+
_Fable.serviceManager.addServiceType('Orator', libOrator);
|
|
30
|
+
_Fable.serviceManager.addServiceType('OratorServiceServer', libOratorServiceServerRestify);
|
|
31
|
+
_Fable.serviceManager.instantiateServiceProvider('Orator');
|
|
32
|
+
_Fable.serviceManager.instantiateServiceProvider('OratorServiceServer');
|
|
20
33
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
var libOrator = require('orator').new(
|
|
34
|
+
_Fable.Orator.serviceServer.get('/hello/:name',
|
|
35
|
+
(pRequest, pResponse, fNext) =>
|
|
24
36
|
{
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"APIServerPort": 8000
|
|
37
|
+
pResponse.send({ greeting: `Hello ${pRequest.params.name}!` });
|
|
38
|
+
return fNext();
|
|
29
39
|
});
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
(
|
|
34
|
-
'/echo/:name',
|
|
35
|
-
function(pRequest, pResponse, fNext)
|
|
41
|
+
_Fable.Orator.startService(
|
|
42
|
+
() =>
|
|
36
43
|
{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return fNext();
|
|
40
|
-
}
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
// Start the web service
|
|
44
|
-
libOrator.startWebServer();
|
|
44
|
+
console.log('Server is running on port 8080');
|
|
45
|
+
});
|
|
45
46
|
```
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Of course, this is not much different from the Restify code. Where it gets interesting is dealing with things like logging and configuration management. For instance, if you do
|
|
48
|
+
## Installation
|
|
50
49
|
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
{
|
|
55
|
-
Product: 'MyMicroserviceHash',
|
|
56
|
-
ProductVersion: '9.8.7',
|
|
50
|
+
```bash
|
|
51
|
+
npm install orator
|
|
52
|
+
```
|
|
57
53
|
|
|
58
|
-
|
|
54
|
+
## Configuration
|
|
59
55
|
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
| Setting | Type | Default | Description |
|
|
57
|
+
|---------|------|---------|-------------|
|
|
58
|
+
| `Product` | string | `"Unnamed_Service"` | Application name identifier |
|
|
59
|
+
| `ProductVersion` | string | `"0.0.1"` | Application version string |
|
|
60
|
+
| `ServicePort` | number | `8080` | Port for the service server to listen on |
|
|
61
|
+
| `APIServerPort` | number | - | Legacy alias for ServicePort (automatically migrated) |
|
|
62
|
+
| `RestifyConfiguration` | object | `{}` | Configuration passed to Restify when using the Restify service server |
|
|
62
63
|
|
|
63
|
-
|
|
64
|
-
libOrator.webServer.post
|
|
65
|
-
(
|
|
66
|
-
'/echo/:name',
|
|
67
|
-
function(pRequest, pResponse, fNext)
|
|
68
|
-
{
|
|
69
|
-
// Send back whatever was sent as "name" in the URI
|
|
70
|
-
pResponse.send(pRequest.params);
|
|
71
|
-
return fNext();
|
|
72
|
-
}
|
|
73
|
-
);
|
|
64
|
+
## Documentation
|
|
74
65
|
|
|
75
|
-
|
|
76
|
-
libOrator.startWebServer();
|
|
77
|
-
```
|
|
66
|
+
Full documentation is available in the [`docs`](./docs) folder, or served locally:
|
|
78
67
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
```json
|
|
82
|
-
{
|
|
83
|
-
"APIServerPort": 8080,
|
|
84
|
-
|
|
85
|
-
"UUID":
|
|
86
|
-
{
|
|
87
|
-
"DataCenter": 0,
|
|
88
|
-
"Worker": 0
|
|
89
|
-
},
|
|
90
|
-
|
|
91
|
-
"LogStreams":
|
|
92
|
-
[
|
|
93
|
-
{
|
|
94
|
-
"level": "info",
|
|
95
|
-
"path": "./MyMicroService-Server.log"
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
"level": "trace",
|
|
99
|
-
"streamtype": "process.stdout"
|
|
100
|
-
}
|
|
101
|
-
]
|
|
102
|
-
}
|
|
68
|
+
```bash
|
|
69
|
+
npx docsify-cli serve docs
|
|
103
70
|
```
|
|
104
71
|
|
|
105
|
-
|
|
72
|
+
- [Architecture](docs/architecture.md) - Service server abstraction design
|
|
73
|
+
- [Getting Started](docs/getting-started.md) - Step-by-step setup guide
|
|
74
|
+
- [Static File Serving](docs/static-files.md) - Serving files from disk
|
|
75
|
+
- [IPC Server](docs/ipc-server.md) - In-process service invocation
|
|
106
76
|
|
|
77
|
+
## Related Packages
|
|
107
78
|
|
|
79
|
+
- [orator-serviceserver-base](https://github.com/stevenvelozo/orator-serviceserver-base) - Abstract base class for service servers
|
|
80
|
+
- [orator-serviceserver-restify](https://github.com/stevenvelozo/orator-serviceserver-restify) - Restify service server implementation
|
|
81
|
+
- [orator-http-proxy](https://github.com/stevenvelozo/orator-http-proxy) - HTTP proxy pass-through for Orator
|
|
82
|
+
- [orator-static-server](https://github.com/stevenvelozo/orator-static-server) - Static file serving module
|
|
83
|
+
- [fable](https://github.com/stevenvelozo/fable) - Service provider framework
|
|
84
|
+
- [meadow](https://github.com/stevenvelozo/meadow) - Data access layer with automatic REST endpoints
|
package/docs/.nojekyll
ADDED
|
File without changes
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Orator
|
|
2
|
+
|
|
3
|
+
> An unopinionated API server abstraction for REST and IPC services
|
|
4
|
+
|
|
5
|
+
Orator is a thin abstraction layer over service server implementations, providing a consistent interface for building API servers. It doesn't care whether you're running Restify, building an in-process service mesh, or doing something entirely novel with your own service server implementation. Orator provides the lifecycle, the configuration, and the conventions -- you provide the service logic.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Unopinionated Design** - Wraps any service server implementation through a consistent interface
|
|
10
|
+
- **REST and IPC** - Full HTTP server support via Restify, or in-process IPC for testing and microservice composition
|
|
11
|
+
- **Lifecycle Management** - Before/After hooks for initialization and service start phases
|
|
12
|
+
- **Static File Serving** - Built-in static file serving with subdomain-based folder routing
|
|
13
|
+
- **Fable Integration** - First-class service provider in the Fable ecosystem with logging and configuration
|
|
14
|
+
- **Browser & Node.js** - Works in both environments with automatic service server selection
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```javascript
|
|
19
|
+
const libFable = require('fable');
|
|
20
|
+
const libOrator = require('orator');
|
|
21
|
+
const libOratorServiceServerRestify = require('orator-serviceserver-restify');
|
|
22
|
+
|
|
23
|
+
const _Fable = new libFable({
|
|
24
|
+
Product: 'MyAPIServer',
|
|
25
|
+
ProductVersion: '1.0.0',
|
|
26
|
+
ServicePort: 8080
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Register Orator and a service server with Fable
|
|
30
|
+
_Fable.serviceManager.addServiceType('Orator', libOrator);
|
|
31
|
+
_Fable.serviceManager.addServiceType('OratorServiceServer', libOratorServiceServerRestify);
|
|
32
|
+
_Fable.serviceManager.instantiateServiceProvider('Orator');
|
|
33
|
+
_Fable.serviceManager.instantiateServiceProvider('OratorServiceServer');
|
|
34
|
+
|
|
35
|
+
// Add an API endpoint
|
|
36
|
+
_Fable.Orator.serviceServer.get('/hello/:name',
|
|
37
|
+
(pRequest, pResponse, fNext) =>
|
|
38
|
+
{
|
|
39
|
+
pResponse.send({ greeting: `Hello ${pRequest.params.name}!` });
|
|
40
|
+
return fNext();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Start the service
|
|
44
|
+
_Fable.Orator.startService(
|
|
45
|
+
() =>
|
|
46
|
+
{
|
|
47
|
+
console.log('Server is running on port 8080');
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npm install orator
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## How It Works
|
|
58
|
+
|
|
59
|
+
Orator follows the Fable service provider pattern. You register it with a Fable instance, and it orchestrates one or more service server implementations to handle incoming requests. If you don't provide a service server, Orator will automatically set up its built-in IPC server -- which is useful for testing and in-process communication where no network traffic is needed.
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
Fable (Core)
|
|
63
|
+
└── Orator (Service Orchestration)
|
|
64
|
+
└── Service Server (Restify, IPC, or custom)
|
|
65
|
+
├── Route Registration (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD)
|
|
66
|
+
├── Middleware Pipeline
|
|
67
|
+
└── Static File Serving
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Configuration
|
|
71
|
+
|
|
72
|
+
Orator accepts configuration through the Fable settings object:
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"Product": "MyAPIServer",
|
|
77
|
+
"ProductVersion": "1.0.0",
|
|
78
|
+
"ServicePort": 8080,
|
|
79
|
+
"RestifyConfiguration": {}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
| Setting | Type | Default | Description |
|
|
84
|
+
|---------|------|---------|-------------|
|
|
85
|
+
| `Product` | string | `"Unnamed_Service"` | Application name identifier |
|
|
86
|
+
| `ProductVersion` | string | `"0.0.1"` | Application version string |
|
|
87
|
+
| `ServicePort` | number | `8080` | Port for the service server to listen on |
|
|
88
|
+
| `APIServerPort` | number | - | Legacy alias for ServicePort (automatically migrated) |
|
|
89
|
+
| `RestifyConfiguration` | object | `{}` | Configuration passed to Restify server creation |
|
|
90
|
+
| `ServiceServerOptions` | object | `{}` | Options passed to the auto-initialized service server |
|
|
91
|
+
|
|
92
|
+
## API Reference
|
|
93
|
+
|
|
94
|
+
### Lifecycle Methods
|
|
95
|
+
|
|
96
|
+
| Method | Description |
|
|
97
|
+
|--------|-------------|
|
|
98
|
+
| `initialize(fCallback)` | Initializes Orator and its service server |
|
|
99
|
+
| `startService(fCallback)` | Starts the service server listening on the configured port |
|
|
100
|
+
| `stopService(fCallback)` | Stops the running service server |
|
|
101
|
+
|
|
102
|
+
### Route Invocation
|
|
103
|
+
|
|
104
|
+
| Method | Description |
|
|
105
|
+
|--------|-------------|
|
|
106
|
+
| `invoke(pMethod, pRoute, pData, fCallback)` | Programmatically invoke a registered route without HTTP |
|
|
107
|
+
|
|
108
|
+
### Static Files
|
|
109
|
+
|
|
110
|
+
| Method | Description |
|
|
111
|
+
|--------|-------------|
|
|
112
|
+
| `addStaticRoute(pFilePath, pDefaultFile, pRoute, pRouteStrip, pParams)` | Serve static files from a directory |
|
|
113
|
+
|
|
114
|
+
### Legacy Methods
|
|
115
|
+
|
|
116
|
+
| Method | Maps To |
|
|
117
|
+
|--------|---------|
|
|
118
|
+
| `startWebServer(fCallback)` | `startService(fCallback)` |
|
|
119
|
+
| `stopWebServer(fCallback)` | `stopService(fCallback)` |
|
|
120
|
+
| `getWebServer()` | Returns `serviceServer` (lazy-initializes if needed) |
|
|
121
|
+
|
|
122
|
+
### Properties
|
|
123
|
+
|
|
124
|
+
| Property | Type | Description |
|
|
125
|
+
|----------|------|-------------|
|
|
126
|
+
| `serviceServer` | object | The active service server instance |
|
|
127
|
+
| `webServer` | object | Legacy alias for `serviceServer` |
|
|
128
|
+
|
|
129
|
+
## Testing
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
npm test
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Related Packages
|
|
136
|
+
|
|
137
|
+
- [orator-serviceserver-base](https://github.com/stevenvelozo/orator-serviceserver-base) - Abstract base class for service servers
|
|
138
|
+
- [orator-serviceserver-restify](https://github.com/stevenvelozo/orator-serviceserver-restify) - Restify service server implementation
|
|
139
|
+
- [orator-http-proxy](https://github.com/stevenvelozo/orator-http-proxy) - HTTP proxy pass-through for Orator
|
|
140
|
+
- [orator-static-server](https://github.com/stevenvelozo/orator-static-server) - Static file serving module
|
|
141
|
+
- [fable](https://github.com/stevenvelozo/fable) - Service provider framework
|
|
142
|
+
- [meadow](https://github.com/stevenvelozo/meadow) - Data access layer with automatic REST endpoints
|
package/docs/_sidebar.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
- Getting Started
|
|
2
|
+
|
|
3
|
+
- [Introduction](/)
|
|
4
|
+
- [Getting Started](getting-started.md)
|
|
5
|
+
- [Architecture](architecture.md)
|
|
6
|
+
|
|
7
|
+
- Core Concepts
|
|
8
|
+
|
|
9
|
+
- [Service Servers](service-servers.md)
|
|
10
|
+
- [Lifecycle Hooks](lifecycle-hooks.md)
|
|
11
|
+
- [Static File Serving](static-files.md)
|
|
12
|
+
|
|
13
|
+
- Service Server Implementations
|
|
14
|
+
|
|
15
|
+
- [IPC Server](ipc-server.md)
|
|
16
|
+
- [Restify Server](restify-server.md)
|
|
17
|
+
|
|
18
|
+
- Advanced
|
|
19
|
+
|
|
20
|
+
- [HTTP Proxy](http-proxy.md)
|
|
21
|
+
- [Configuration Reference](configuration.md)
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
Orator's design separates the concerns of service lifecycle management from the specifics of any HTTP server implementation. This abstraction allows you to swap service servers, test without network overhead, and maintain consistent patterns across many microservices.
|
|
4
|
+
|
|
5
|
+
## Layered Design
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌─────────────────────────────────────────────┐
|
|
9
|
+
│ Fable │
|
|
10
|
+
│ (Configuration, Logging, DI) │
|
|
11
|
+
└─────────────────────┬───────────────────────┘
|
|
12
|
+
│
|
|
13
|
+
┌─────────────────────▼───────────────────────┐
|
|
14
|
+
│ Orator │
|
|
15
|
+
│ (Lifecycle, Static Files, Invocation) │
|
|
16
|
+
└─────────────────────┬───────────────────────┘
|
|
17
|
+
│
|
|
18
|
+
┌─────────────────────▼───────────────────────┐
|
|
19
|
+
│ OratorServiceServerBase │
|
|
20
|
+
│ (Abstract Route & Middleware API) │
|
|
21
|
+
└───────┬─────────────┬───────────────────────┘
|
|
22
|
+
│ │
|
|
23
|
+
┌───────▼──────┐ ┌────▼──────────────┐
|
|
24
|
+
│ IPC Server │ │ Restify Server │
|
|
25
|
+
│ (built-in) │ │ (network HTTP) │
|
|
26
|
+
└──────────────┘ └───────────────────┘
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Fable Layer
|
|
30
|
+
|
|
31
|
+
Fable provides the foundation: dependency injection, configuration management, logging, and service wiring. Orator registers itself as a Fable service and gains access to all of these capabilities automatically.
|
|
32
|
+
|
|
33
|
+
### Orator Layer
|
|
34
|
+
|
|
35
|
+
Orator manages the service lifecycle (initialization, starting, stopping) and provides higher-level features like static file serving and programmatic route invocation. It delegates actual HTTP handling to whichever service server implementation is registered.
|
|
36
|
+
|
|
37
|
+
### Service Server Layer
|
|
38
|
+
|
|
39
|
+
Service servers implement the actual HTTP verb handling. The base class (`orator-serviceserver-base`) defines the interface, and concrete implementations like `orator-serviceserver-restify` and the built-in IPC server provide the behavior.
|
|
40
|
+
|
|
41
|
+
## Service Provider Pattern
|
|
42
|
+
|
|
43
|
+
All Orator modules follow the Fable service provider pattern. Services are registered with a Fable instance by type, then instantiated on demand:
|
|
44
|
+
|
|
45
|
+
```javascript
|
|
46
|
+
// Register the service types
|
|
47
|
+
_Fable.serviceManager.addServiceType('Orator', libOrator);
|
|
48
|
+
_Fable.serviceManager.addServiceType('OratorServiceServer', libOratorServiceServerRestify);
|
|
49
|
+
|
|
50
|
+
// Instantiate them -- Fable handles wiring
|
|
51
|
+
_Fable.serviceManager.instantiateServiceProvider('Orator');
|
|
52
|
+
_Fable.serviceManager.instantiateServiceProvider('OratorServiceServer');
|
|
53
|
+
|
|
54
|
+
// Access via Fable
|
|
55
|
+
_Fable.Orator.startService();
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Auto-Initialization
|
|
59
|
+
|
|
60
|
+
If no service server is registered when Orator initializes, it will automatically create and register the built-in IPC service server. This makes it possible to use Orator for in-process route invocation without configuring a network server:
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
// No OratorServiceServer registered -- IPC is used automatically
|
|
64
|
+
_Fable.serviceManager.addServiceType('Orator', libOrator);
|
|
65
|
+
_Fable.serviceManager.instantiateServiceProvider('Orator');
|
|
66
|
+
|
|
67
|
+
_Fable.Orator.serviceServer.get('/api/data',
|
|
68
|
+
(pRequest, pResponse, fNext) =>
|
|
69
|
+
{
|
|
70
|
+
pResponse.send({ value: 42 });
|
|
71
|
+
return fNext();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Invoke the route programmatically (no network call)
|
|
75
|
+
_Fable.Orator.invoke('GET', '/api/data', {},
|
|
76
|
+
(pError, pResponseData) =>
|
|
77
|
+
{
|
|
78
|
+
console.log(pResponseData); // { value: 42 }
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Template Method Pattern
|
|
83
|
+
|
|
84
|
+
The service server base class uses a template method pattern for route registration. The base class validates inputs, and derived classes implement the `do*` methods with actual behavior:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
Base: get(pRoute, ...) → validates pRoute → calls doGet(pRoute, ...)
|
|
88
|
+
└── Restify: doGet(pRoute, ...) → this.server.get(pRoute, ...)
|
|
89
|
+
└── IPC: doGet(pRoute, ...) → this.addRouteProcessor('GET', pRoute, ...)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
This pattern allows derived classes to focus on implementation without duplicating validation logic.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Configuration Reference
|
|
2
|
+
|
|
3
|
+
Orator is configured through the Fable settings object. Settings can be provided directly, loaded from a configuration file, or a combination of both.
|
|
4
|
+
|
|
5
|
+
## Orator Settings
|
|
6
|
+
|
|
7
|
+
| Setting | Type | Default | Description |
|
|
8
|
+
|---------|------|---------|-------------|
|
|
9
|
+
| `Product` | string | `"Unnamed_Service"` | Application name identifier |
|
|
10
|
+
| `ProductVersion` | string | `"0.0.1"` | Application version string |
|
|
11
|
+
| `ServicePort` | number | `8080` | Port for the service server to listen on |
|
|
12
|
+
| `APIServerPort` | number | - | Legacy alias for `ServicePort` (automatically migrated) |
|
|
13
|
+
| `ServiceServerOptions` | object | `{}` | Options passed to the auto-initialized service server |
|
|
14
|
+
|
|
15
|
+
## Restify Settings
|
|
16
|
+
|
|
17
|
+
When using the Restify service server:
|
|
18
|
+
|
|
19
|
+
| Setting | Type | Default | Description |
|
|
20
|
+
|---------|------|---------|-------------|
|
|
21
|
+
| `RestifyConfiguration` | object | `{}` | Configuration passed to `restify.createServer()` |
|
|
22
|
+
| `RestifyConfiguration.maxParamLength` | number | `Number.MAX_SAFE_INTEGER` | Maximum URL parameter length |
|
|
23
|
+
|
|
24
|
+
## HTTP Proxy Settings
|
|
25
|
+
|
|
26
|
+
When using the HTTP proxy module:
|
|
27
|
+
|
|
28
|
+
| Setting | Type | Default | Description |
|
|
29
|
+
|---------|------|---------|-------------|
|
|
30
|
+
| `OratorHTTPProxyDestinationURL` | string | `"http://127.0.0.1/"` | URL to proxy requests to |
|
|
31
|
+
| `OratorHTTPProxyRequestPrefixList` | array | `["/1.0/*"]` | Route prefixes to proxy |
|
|
32
|
+
| `OratorHTTPProxyLogLevel` | number | `0` | Proxy logging verbosity |
|
|
33
|
+
|
|
34
|
+
## Fable Settings
|
|
35
|
+
|
|
36
|
+
These Fable settings are commonly used with Orator:
|
|
37
|
+
|
|
38
|
+
| Setting | Type | Default | Description |
|
|
39
|
+
|---------|------|---------|-------------|
|
|
40
|
+
| `LogStreams` | array | `[{ level: "info" }]` | Log output destinations |
|
|
41
|
+
| `LogNoisiness` | number | `0` | Controls Orator's internal trace logging |
|
|
42
|
+
| `UUID.DataCenter` | number | `0` | Data center ID for UUID generation |
|
|
43
|
+
| `UUID.Worker` | number | `0` | Worker ID for UUID generation |
|
|
44
|
+
|
|
45
|
+
## Example Configuration File
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"Product": "MyAPIServer",
|
|
50
|
+
"ProductVersion": "2.1.0",
|
|
51
|
+
"ServicePort": 8080,
|
|
52
|
+
|
|
53
|
+
"RestifyConfiguration": {
|
|
54
|
+
"strictNext": true
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
"UUID": {
|
|
58
|
+
"DataCenter": 0,
|
|
59
|
+
"Worker": 1
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
"LogStreams": [
|
|
63
|
+
{
|
|
64
|
+
"level": "info",
|
|
65
|
+
"path": "./server.log"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"level": "trace",
|
|
69
|
+
"streamtype": "process.stdout"
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Loading Configuration
|
|
76
|
+
|
|
77
|
+
```javascript
|
|
78
|
+
// Direct configuration
|
|
79
|
+
const _Fable = new libFable({
|
|
80
|
+
Product: 'MyAPIServer',
|
|
81
|
+
ServicePort: 8080
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// From a JSON file
|
|
85
|
+
const _Fable = new libFable({
|
|
86
|
+
ConfigFile: __dirname + '/config.json'
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Combined (direct settings override file settings)
|
|
90
|
+
const _Fable = new libFable({
|
|
91
|
+
ConfigFile: __dirname + '/config.json',
|
|
92
|
+
ServicePort: 9090 // Overrides whatever is in config.json
|
|
93
|
+
});
|
|
94
|
+
```
|
package/docs/cover.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Orator <small>5</small>
|
|
2
|
+
|
|
3
|
+
> An unopinionated API server abstraction for REST and IPC services
|
|
4
|
+
|
|
5
|
+
- Consistent interface over any service server implementation
|
|
6
|
+
- Full REST support via Restify with in-process IPC for testing
|
|
7
|
+
- Built-in static file serving with subdomain routing
|
|
8
|
+
- First-class Fable service provider with lifecycle management
|
|
9
|
+
|
|
10
|
+
[GitHub](https://github.com/stevenvelozo/orator)
|
|
11
|
+
[Get Started](#orator)
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Getting Started
|
|
2
|
+
|
|
3
|
+
This guide walks through setting up an Orator-based API server from scratch.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Create a new Node.js project and install the dependencies:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
mkdir my-api-server && cd my-api-server
|
|
11
|
+
npm init -y
|
|
12
|
+
npm install fable orator orator-serviceserver-restify
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Basic Server
|
|
16
|
+
|
|
17
|
+
The simplest possible Orator server:
|
|
18
|
+
|
|
19
|
+
```javascript
|
|
20
|
+
const libFable = require('fable');
|
|
21
|
+
const libOrator = require('orator');
|
|
22
|
+
const libOratorServiceServerRestify = require('orator-serviceserver-restify');
|
|
23
|
+
|
|
24
|
+
// 1. Create a Fable instance with your service configuration
|
|
25
|
+
const _Fable = new libFable({
|
|
26
|
+
Product: 'MyAPIServer',
|
|
27
|
+
ProductVersion: '1.0.0',
|
|
28
|
+
ServicePort: 8080
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// 2. Register Orator and a service server
|
|
32
|
+
_Fable.serviceManager.addServiceType('Orator', libOrator);
|
|
33
|
+
_Fable.serviceManager.addServiceType('OratorServiceServer', libOratorServiceServerRestify);
|
|
34
|
+
_Fable.serviceManager.instantiateServiceProvider('Orator');
|
|
35
|
+
_Fable.serviceManager.instantiateServiceProvider('OratorServiceServer');
|
|
36
|
+
|
|
37
|
+
// 3. Define your API endpoints
|
|
38
|
+
_Fable.Orator.serviceServer.get('/api/status',
|
|
39
|
+
(pRequest, pResponse, fNext) =>
|
|
40
|
+
{
|
|
41
|
+
pResponse.send({ status: 'ok', timestamp: new Date().toISOString() });
|
|
42
|
+
return fNext();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// 4. Start the server
|
|
46
|
+
_Fable.Orator.startService(
|
|
47
|
+
() =>
|
|
48
|
+
{
|
|
49
|
+
_Fable.log.info('API server is ready');
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Run it with `node server.js` and visit `http://localhost:8080/api/status` in your browser.
|
|
54
|
+
|
|
55
|
+
## Adding Routes
|
|
56
|
+
|
|
57
|
+
Orator's service server exposes methods for all standard HTTP verbs. Each handler receives `pRequest`, `pResponse`, and `fNext` -- the standard Restify handler signature.
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
// GET with URL parameters
|
|
61
|
+
_Fable.Orator.serviceServer.get('/api/user/:id',
|
|
62
|
+
(pRequest, pResponse, fNext) =>
|
|
63
|
+
{
|
|
64
|
+
let tmpUserID = pRequest.params.id;
|
|
65
|
+
pResponse.send({ id: tmpUserID, name: 'Example User' });
|
|
66
|
+
return fNext();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// POST with body parsing
|
|
70
|
+
_Fable.Orator.serviceServer.postWithBodyParser('/api/user',
|
|
71
|
+
(pRequest, pResponse, fNext) =>
|
|
72
|
+
{
|
|
73
|
+
let tmpNewUser = pRequest.body;
|
|
74
|
+
_Fable.log.info(`Creating user: ${tmpNewUser.name}`);
|
|
75
|
+
pResponse.send({ created: true, user: tmpNewUser });
|
|
76
|
+
return fNext();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// PUT, DELETE, PATCH follow the same pattern
|
|
80
|
+
_Fable.Orator.serviceServer.del('/api/user/:id',
|
|
81
|
+
(pRequest, pResponse, fNext) =>
|
|
82
|
+
{
|
|
83
|
+
pResponse.send({ deleted: true, id: pRequest.params.id });
|
|
84
|
+
return fNext();
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Using Middleware
|
|
89
|
+
|
|
90
|
+
Register middleware that runs before all route handlers:
|
|
91
|
+
|
|
92
|
+
```javascript
|
|
93
|
+
// Add a middleware function
|
|
94
|
+
_Fable.Orator.serviceServer.use(
|
|
95
|
+
(pRequest, pResponse, fNext) =>
|
|
96
|
+
{
|
|
97
|
+
_Fable.log.trace(`${pRequest.method} ${pRequest.url}`);
|
|
98
|
+
return fNext();
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Configuration from File
|
|
103
|
+
|
|
104
|
+
Fable supports loading configuration from a JSON file, which means your Orator server configuration can live outside your code:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"Product": "MyAPIServer",
|
|
109
|
+
"ProductVersion": "1.0.0",
|
|
110
|
+
"ServicePort": 8080,
|
|
111
|
+
"LogStreams": [
|
|
112
|
+
{
|
|
113
|
+
"level": "info",
|
|
114
|
+
"path": "./server.log"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"level": "trace",
|
|
118
|
+
"streamtype": "process.stdout"
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
const _Fable = new libFable({ ConfigFile: __dirname + '/config.json' });
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Next Steps
|
|
129
|
+
|
|
130
|
+
- [Architecture](architecture.md) - Understand the service server abstraction
|
|
131
|
+
- [Lifecycle Hooks](lifecycle-hooks.md) - Customize initialization and startup behavior
|
|
132
|
+
- [Static File Serving](static-files.md) - Serve files from disk
|
|
133
|
+
- [IPC Server](ipc-server.md) - Use Orator without a network server
|