@vida-global/core 1.1.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/README.md +9 -0
- package/index.js +17 -0
- package/lib/active_record/README.md +205 -0
- package/lib/active_record/baseRecord.js +112 -0
- package/lib/active_record/db/connection.js +128 -0
- package/lib/active_record/db/connectionConfiguration.js +114 -0
- package/lib/active_record/db/importSchema.js +4 -0
- package/lib/active_record/db/migration.js +132 -0
- package/lib/active_record/db/migrationTemplate.js +8 -0
- package/lib/active_record/db/migrationVersion.js +68 -0
- package/lib/active_record/db/migrator.js +169 -0
- package/lib/active_record/db/queryInterface.js +47 -0
- package/lib/active_record/db/schema.js +113 -0
- package/lib/active_record/index.js +6 -0
- package/lib/active_record/utils.js +43 -0
- package/lib/http/README.md +32 -0
- package/lib/http/client.js +129 -0
- package/lib/http/error.js +34 -0
- package/lib/logger/README.md +2 -0
- package/lib/logger/index.js +16 -0
- package/lib/release/develop.js +27 -0
- package/lib/release/git.js +86 -0
- package/lib/release/increment.js +56 -0
- package/lib/release/index.js +10 -0
- package/lib/release/release.js +30 -0
- package/lib/release/utils.js +44 -0
- package/lib/server/README.md +37 -0
- package/lib/server/index.js +9 -0
- package/lib/server/server.js +359 -0
- package/lib/server/serverController.js +344 -0
- package/lib/server/systemController.js +23 -0
- package/package.json +37 -0
- package/scripts/active_record/migrate.js +30 -0
- package/scripts/release.js +62 -0
- package/test/active_record/baseRecord.test.js +179 -0
- package/test/active_record/db/connection.test.js +221 -0
- package/test/active_record/db/connectionConfiguration.test.js +184 -0
- package/test/active_record/db/migrator.test.js +266 -0
- package/test/active_record/db/queryInterface.test.js +66 -0
- package/test/http/client.test.js +271 -0
- package/test/http/error.test.js +71 -0
- package/test/release/develop.test.js +57 -0
- package/test/release/git.test.js +189 -0
- package/test/release/increment.test.js +145 -0
- package/test/release/release.test.js +72 -0
- package/test/release/utils.test.js +148 -0
- package/test/server/helpers/controllers/barController.js +9 -0
- package/test/server/helpers/controllers/fooController.js +48 -0
- package/test/server/helpers/controllers/sub/bazController.js +10 -0
- package/test/server/helpers/server.js +14 -0
- package/test/server/server.test.js +188 -0
- package/test/server/serverController.test.js +251 -0
package/README.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Vida/Core
|
|
2
|
+
This package is intended to contain core elements used across all Vida Apps. Keep in mind that it's included in the `vida-apps-tools` package, so customers developing Vida Apps will have access to it.
|
|
3
|
+
|
|
4
|
+
# Guides
|
|
5
|
+
|
|
6
|
+
- [ActiveRecord](lib/active_record)
|
|
7
|
+
- [HttpClient](lib/http)
|
|
8
|
+
- [Logger](lib/logger)
|
|
9
|
+
- [VidaServer](lib/server)
|
package/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const { HttpClient, HttpError } = require('./lib/http/client');
|
|
2
|
+
const { AuthorizationError,
|
|
3
|
+
VidaServer,
|
|
4
|
+
VidaServerController } = require('./lib/server');
|
|
5
|
+
const { logger } = require('./lib/logger');
|
|
6
|
+
const ActiveRecord = require('./lib/active_record');
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
module.exports = {
|
|
10
|
+
ActiveRecord,
|
|
11
|
+
AuthorizationError,
|
|
12
|
+
HttpClient,
|
|
13
|
+
HttpError,
|
|
14
|
+
logger,
|
|
15
|
+
VidaServer,
|
|
16
|
+
VidaServerController,
|
|
17
|
+
};
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
To configure your database, create a `config.js` file in the `config/db/` directory of your project. That file should follow this format:
|
|
3
|
+
```
|
|
4
|
+
module.exports = {
|
|
5
|
+
default: {
|
|
6
|
+
development: {
|
|
7
|
+
database: process.env.DATABASE,
|
|
8
|
+
host: process.env.DB_HOST,
|
|
9
|
+
password: process.env.DB_PASSWORD,
|
|
10
|
+
username: process.env.DB_USERNAME
|
|
11
|
+
},
|
|
12
|
+
production: {
|
|
13
|
+
...
|
|
14
|
+
},
|
|
15
|
+
...
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Add additional entries for multiple databases
|
|
21
|
+
```
|
|
22
|
+
module.exports = {
|
|
23
|
+
default: {
|
|
24
|
+
...
|
|
25
|
+
},
|
|
26
|
+
metrics: {
|
|
27
|
+
development: {
|
|
28
|
+
database: process.env.DATABASE,
|
|
29
|
+
host: process.env.DB_HOST,
|
|
30
|
+
password: process.env.DB_PASSWORD,
|
|
31
|
+
username: process.env.DB_USERNAME
|
|
32
|
+
},
|
|
33
|
+
production: {
|
|
34
|
+
...
|
|
35
|
+
},
|
|
36
|
+
...
|
|
37
|
+
},
|
|
38
|
+
...
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
### Connection Pooling
|
|
44
|
+
Minimum and maximum connection pool sizes can be configured in config.js, but default to 0 and 5, respectively.
|
|
45
|
+
```
|
|
46
|
+
development: {
|
|
47
|
+
database: process.env.DATABASE,
|
|
48
|
+
host: process.env.DB_HOST,
|
|
49
|
+
password: process.env.DB_PASSWORD,
|
|
50
|
+
username: process.env.DB_USERNAME,
|
|
51
|
+
pool: {
|
|
52
|
+
min: 1,
|
|
53
|
+
max: 10
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
### Replication
|
|
60
|
+
Read replicas can be configured by adding a `readers` key to your configuration
|
|
61
|
+
```
|
|
62
|
+
development: {
|
|
63
|
+
database: process.env.DATABASE,
|
|
64
|
+
host: process.env.DB_HOST,
|
|
65
|
+
password: process.env.DB_PASSWORD,
|
|
66
|
+
username: process.env.DB_USERNAME,
|
|
67
|
+
readers: [
|
|
68
|
+
{
|
|
69
|
+
database: ...
|
|
70
|
+
host: ...
|
|
71
|
+
password: ...
|
|
72
|
+
username: ...
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
...
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
# Migrations
|
|
83
|
+
To prepare your project to run database migrations, add the following lines to the `scripts` section of your `package.json`:
|
|
84
|
+
```
|
|
85
|
+
"db:create_migration": "node node_modules/@vida-global/core/scripts/active_record/migrate.js create_migration",
|
|
86
|
+
"db:migrate": "node node_modules/@vida-global/core/scripts/active_record/migrate.js migrate",
|
|
87
|
+
"db:rollback": "node node_modules/@vida-global/core/scripts/active_record/migrate.js rollback"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
To generate a new migration file, run: `npm run db:create_migration createUsers`. This will automatically generate a migration file. Your migration can create tables, create indexes, and add, remove, or update columns.
|
|
91
|
+
```
|
|
92
|
+
module.exports = {
|
|
93
|
+
up: async function() {
|
|
94
|
+
await this.createTable('users', {
|
|
95
|
+
email: this.DataTypes.STRING,
|
|
96
|
+
team_id: this.DataTypes.INTEGER,
|
|
97
|
+
is_admin: {
|
|
98
|
+
type: this.DataTypes.BOOLEAN,
|
|
99
|
+
defaultValue: false,
|
|
100
|
+
allowNull: false,
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
await this.addIndex('users', ['team_id'], {where: {team_id: {[this.Operators.ne]: null}}});
|
|
105
|
+
await this.addIndex('users', ['email'], {unique: true});
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
down: async function () {
|
|
109
|
+
await this.dropTable('users');
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
Available migrations are:
|
|
114
|
+
```
|
|
115
|
+
createTable(tableName, details)
|
|
116
|
+
dropTable(tableName)
|
|
117
|
+
addColumn(tableName, columnName, columnDetails)
|
|
118
|
+
removeColumn(tableName, columnName)
|
|
119
|
+
addIndex(tableName, fields, { concurrently, unique, name, where })
|
|
120
|
+
removeIndex(tableName, indexNameOrAttributes, concurrently=false)
|
|
121
|
+
renameColumn(tableName, oldName, newName)
|
|
122
|
+
changeColumn(tableName, columnName, dataTypeOrOptions)
|
|
123
|
+
```
|
|
124
|
+
To run your migrations, run `npm run db:migrate` or `npm run db:rollback` to rollback a single migration.
|
|
125
|
+
|
|
126
|
+
**NOTE**: By default, `createTable` automatically adds an autoincrement, primary key `id` column, a `created_at` column, and an `updated_at` column.
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
# Models
|
|
130
|
+
The following code will create a basic model representing a user in our database:
|
|
131
|
+
```
|
|
132
|
+
const { ActiveRecord } = require('@vida-global/core')
|
|
133
|
+
|
|
134
|
+
class User extends ActiveRecord.BaseRecord {
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
User.initialize();
|
|
138
|
+
|
|
139
|
+
const user = new User({email: 'mark@vida.inc', team_id: 1, is_admin: false});
|
|
140
|
+
await user.save();
|
|
141
|
+
|
|
142
|
+
user.is_admin = true;
|
|
143
|
+
await user.save();
|
|
144
|
+
|
|
145
|
+
await user.destroy();
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
### Querying Models
|
|
150
|
+
```
|
|
151
|
+
const users = await User.findAll();
|
|
152
|
+
const users = await User.findAll{where: {team_id: 1}});
|
|
153
|
+
const users = await User.findAll{where: User.Operator
|
|
154
|
+
|
|
155
|
+
const users = await User.findAll({where: {
|
|
156
|
+
team_id: {
|
|
157
|
+
[Recording.Operators.or]: [1,2]
|
|
158
|
+
}
|
|
159
|
+
}});
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
### Aggregators and Functions
|
|
165
|
+
```
|
|
166
|
+
const rows = await User.findAll({
|
|
167
|
+
attributes: ['team_id', [User.fn('MAX', User.col('id')), 'max_id']],
|
|
168
|
+
group: 'team_id'
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
const { count, users } = await User.findAndCountAll({
|
|
172
|
+
where: {
|
|
173
|
+
email: {
|
|
174
|
+
[User.Operators.like]: '%@vida.inc',
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
offset: 0,
|
|
178
|
+
limit: 1,
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
const totalCount = await User.count({where: {team_id: 1}});
|
|
182
|
+
```
|
|
183
|
+
More examples can be found here, https://sequelize.org/docs/v6/core-concepts/model-querying-basics/.
|
|
184
|
+
|
|
185
|
+
**Note** The `sequelize.fn`, `sequelize.col`, and `Op` properties have been added as helpers on the Model (e.g. `User.fn('MAX', User.col('id'), 'max_id')` and `User.Operators.or`)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
### Associations
|
|
189
|
+
**TODO**
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
### Validators
|
|
193
|
+
**TODO**
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
### Hooks
|
|
197
|
+
**TODO**
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
### Paranoid
|
|
201
|
+
**TODO**
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
# Closing Connections
|
|
205
|
+
When cleaning up your application, close all open connections with `User.closeAllConnections()`. This will close all connections for all models, not just the `User` model.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
const { Connection, DEFAULT_DATABASE_ID } = require('./db/connection');
|
|
2
|
+
const { getActiveRecordSchema } = require('./db/schema');
|
|
3
|
+
const { Model, Op } = require('sequelize');
|
|
4
|
+
const { tableize } = require('inflection');
|
|
5
|
+
const utils = require('./utils');
|
|
6
|
+
const nodeUtil = require('util');
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class BaseRecord extends Model {
|
|
11
|
+
static _connection;
|
|
12
|
+
static _initialized = false;
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
static Operators = Op;
|
|
16
|
+
static get fn() { return this.connection._sequelize.fn }
|
|
17
|
+
static get col() { return this.connection._sequelize.col }
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
constructor() {
|
|
21
|
+
if (new.target == BaseRecord) throw new Error("BaseRecord must be subclasses");
|
|
22
|
+
super(...arguments);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
/***********************************************************************************************
|
|
27
|
+
* QUERIES
|
|
28
|
+
***********************************************************************************************/
|
|
29
|
+
static async find(id) {
|
|
30
|
+
return await this.findByPk(id);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
static async where(where, options={}) {
|
|
35
|
+
const parameters = {...options, where };
|
|
36
|
+
return await this.findAll(parameters);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
/***********************************************************************************************
|
|
41
|
+
* INITIALIZATION
|
|
42
|
+
***********************************************************************************************/
|
|
43
|
+
static initialize() {
|
|
44
|
+
if (this == BaseRecord) throw new Error("BaseRecord must be subclasses");
|
|
45
|
+
|
|
46
|
+
if (this._initialized) return;
|
|
47
|
+
|
|
48
|
+
const schema = getActiveRecordSchema(this._tableName, this.databaseId, this.connection.dialect);
|
|
49
|
+
const options = {
|
|
50
|
+
createdAt: 'created_at',
|
|
51
|
+
deletedAt: 'deleted_at',
|
|
52
|
+
modelName: this.name,
|
|
53
|
+
sequelize: this.connection._sequelize,
|
|
54
|
+
tableName: this._tableName,
|
|
55
|
+
updatedAt: 'updated_at',
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (!schema.created_at || !schema.updated_at) {
|
|
59
|
+
options.timestamps = false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
this.init(schema, options);
|
|
63
|
+
|
|
64
|
+
this._initialized = true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
/***********************************************************************************************
|
|
69
|
+
* DB CONNECTION
|
|
70
|
+
***********************************************************************************************/
|
|
71
|
+
static get connection() {
|
|
72
|
+
if (!this._connection) {
|
|
73
|
+
this._connection = new Connection(this.constructor.databaseId);
|
|
74
|
+
}
|
|
75
|
+
return this._connection;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
static get databaseId() {
|
|
80
|
+
return DEFAULT_DATABASE_ID;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
static get _tableName() {
|
|
85
|
+
return tableize(this.name);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
static closeConnection() {
|
|
90
|
+
this.connection.close();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
static closeAllConnections() {
|
|
95
|
+
Connection.closeAll();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
/***********************************************************************************************
|
|
100
|
+
* MISC
|
|
101
|
+
***********************************************************************************************/
|
|
102
|
+
[nodeUtil.inspect.custom](opts) {
|
|
103
|
+
const args = Array.from(arguments);
|
|
104
|
+
args.shift();
|
|
105
|
+
return nodeUtil.inspect(this.dataValues, ...args);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
module.exports = {
|
|
111
|
+
BaseRecord
|
|
112
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
const { QueryInterface } = require('./queryInterface');
|
|
2
|
+
const { ConnectionConfiguration } = require('./connectionConfiguration');
|
|
3
|
+
const { Sequelize } = require('sequelize');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
let sequelizeConnectionsCache = {};
|
|
7
|
+
const DEFAULT_DATABASE_ID = 'default';
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Connection {
|
|
11
|
+
#configuration;
|
|
12
|
+
#databaseId;
|
|
13
|
+
#options;
|
|
14
|
+
|
|
15
|
+
constructor(databaseId, options={}) {
|
|
16
|
+
this.#databaseId = databaseId || DEFAULT_DATABASE_ID;
|
|
17
|
+
this.#configuration = new ConnectionConfiguration(this.#databaseId);
|
|
18
|
+
this.#options = options;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
close() {
|
|
23
|
+
this._sequelize.close();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
static closeAll() {
|
|
28
|
+
Object.values(sequelizeConnectionsCache).forEach(sequelize => {
|
|
29
|
+
sequelize.close();
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
static clearConnectionsCache() {
|
|
35
|
+
this.closeAll();
|
|
36
|
+
sequelizeConnectionsCache = {};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
get queryInterface() {
|
|
41
|
+
return new QueryInterface(this);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
get _sequelize() {
|
|
46
|
+
if (sequelizeConnectionsCache[this.#databaseId]) return sequelizeConnectionsCache[this.#databaseId];
|
|
47
|
+
|
|
48
|
+
const connection = new Sequelize(null, null, null, this.sequelizeOptions);
|
|
49
|
+
sequelizeConnectionsCache[this.#databaseId] = connection;
|
|
50
|
+
|
|
51
|
+
return connection;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
get sequelizeOptions() {
|
|
56
|
+
const options = {
|
|
57
|
+
...this.dialectOptions,
|
|
58
|
+
define: { underscored: true },
|
|
59
|
+
dialect: this.dialect,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
if (!this.loggingEnabled) options.logging = false;
|
|
63
|
+
|
|
64
|
+
return options;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
get dialectOptions() {
|
|
69
|
+
if (this.dialect == 'sqlite') {
|
|
70
|
+
return this.sqliteSequelizeOptions;
|
|
71
|
+
} else {
|
|
72
|
+
return this.postgresSequelizeOptions;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
get postgresSequelizeOptions() {
|
|
78
|
+
const options = {
|
|
79
|
+
pool: this.#configuration.pool,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const primaryConfig = {
|
|
83
|
+
database: this.#configuration.database,
|
|
84
|
+
host: this.#configuration.host,
|
|
85
|
+
password: this.#configuration.password,
|
|
86
|
+
port: this.#configuration.port,
|
|
87
|
+
username: this.#configuration.username
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
if (this.#configuration.readers.length) {
|
|
91
|
+
options.replication = {
|
|
92
|
+
write: primaryConfig,
|
|
93
|
+
read: this.#configuration.readers
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
Object.assign(options, primaryConfig);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (this.#configuration.ssl) options.dialectOptions = {ssl: {require: true}};
|
|
100
|
+
return options;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
get sqliteSequelizeOptions() {
|
|
105
|
+
return {
|
|
106
|
+
storage: this.#configuration.storage
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
get loggingEnabled() {
|
|
112
|
+
if (this.#options.hasOwnProperty('loggingEnabled')) {
|
|
113
|
+
return this.#options.loggingEnabled;
|
|
114
|
+
}
|
|
115
|
+
return this.#configuration.loggingEnabled;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
get dialect() {
|
|
120
|
+
return this.#configuration.dialect;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
module.exports = {
|
|
126
|
+
Connection,
|
|
127
|
+
DEFAULT_DATABASE_ID
|
|
128
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
const utils = require('../utils');
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class ConnectionConfiguration {
|
|
5
|
+
#_config;
|
|
6
|
+
#databaseId;
|
|
7
|
+
|
|
8
|
+
constructor(databaseId) {
|
|
9
|
+
this.#databaseId = databaseId;
|
|
10
|
+
this.#validateConfiguration();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
get databaseId() { return this.#databaseId };
|
|
15
|
+
|
|
16
|
+
get dialect() { return this.#config.dialect || 'postgres' };
|
|
17
|
+
get database() { return this.#config.database };
|
|
18
|
+
get host() { return this.#config.host };
|
|
19
|
+
get password() { return this.#config.password };
|
|
20
|
+
get port() { return this.#config.port || 5432 };
|
|
21
|
+
get username() { return this.#config.username };
|
|
22
|
+
get ssl() { return Boolean(this.#config.ssl) };
|
|
23
|
+
get storage() { return `${utils.configDirectory}/database.${this.env}.sqlite` };
|
|
24
|
+
|
|
25
|
+
get readers() { return this.#config.readers || [] };
|
|
26
|
+
|
|
27
|
+
get pool() { return {min: this.#poolMin, max: this.#poolMax}}
|
|
28
|
+
get #poolMin() { return this.#config.pool?.min || 0 }
|
|
29
|
+
get #poolMax() { return this.#config.pool?.max || 5 }
|
|
30
|
+
|
|
31
|
+
get loggingEnabled() { return this.env == 'development' };
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
#validateConfiguration() {
|
|
35
|
+
const config = this.#config;
|
|
36
|
+
this.#keysToValidate.forEach(key => {
|
|
37
|
+
if (!config[key]) throw new Error(`Missing ${key} for database configuration ${this.#configId}`);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
get #keysToValidate() {
|
|
43
|
+
if (this.dialect == 'postgres') {
|
|
44
|
+
return ['database', 'host', 'password', 'username'];
|
|
45
|
+
}
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
get #configId() {
|
|
51
|
+
return `${this.#databaseId}.${this.env}`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
get #config() {
|
|
56
|
+
if (this.#_config) return this.#_config[this.env];
|
|
57
|
+
|
|
58
|
+
if (!this._allConfigs) throw new Error(`Missing database configuration`);
|
|
59
|
+
|
|
60
|
+
const config = this._allConfigs[this.#databaseId];
|
|
61
|
+
if (!config || !config[this.env]) throw new Error(`Missing database configuration for ${this.#configId}`);
|
|
62
|
+
|
|
63
|
+
this.#_config = config;
|
|
64
|
+
return this.#_config[this.env];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
/***********************************************************************************************
|
|
69
|
+
* "ALL" CONFIGS
|
|
70
|
+
***********************************************************************************************/
|
|
71
|
+
static get _allConfigs() {
|
|
72
|
+
return structuredClone(this._fetchAllConfigs());
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
static _fetchAllConfigs() {
|
|
77
|
+
try {
|
|
78
|
+
return require(this.configFilePath);
|
|
79
|
+
} catch(err) {
|
|
80
|
+
throw new Error(`Missing or invalid ${this.configFilePath}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
static get configFilePath() {
|
|
86
|
+
return `${utils.configDirectory}/config.js`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
static get env() {
|
|
91
|
+
return process.env.NODE_ENV || 'development';
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
get _allConfigs() { return this.constructor._allConfigs; }
|
|
96
|
+
get configFilePath() { return this.constructor.configFilePath; }
|
|
97
|
+
get env() { return this.constructor.env; }
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
static configuredDatabaseIds() {
|
|
101
|
+
const databaseIds = [];
|
|
102
|
+
|
|
103
|
+
for (const [databaseId, config] of Object.entries(this._allConfigs)) {
|
|
104
|
+
if (config[this.env]) databaseIds.push(databaseId);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return databaseIds
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
module.exports = {
|
|
113
|
+
ConnectionConfiguration
|
|
114
|
+
};
|