@travetto/model-mongo
Version:
Mongo backing for the travetto model module.
125 lines (117 loc) • 3.34 kB
text/typescript
import type mongo from 'mongodb';
import { type TimeSpan, TimeUtil, RuntimeResources, Runtime } from '@travetto/runtime';
import { Config } from '@travetto/config';
/**
* Mongo model config
*/
export class MongoModelConfig {
/**
* Hosts
*/
hosts?: string[];
/**
* Collection prefix
*/
namespace?: string;
/**
* Username
*/
username?: string;
/**
* Password
*/
password?: string;
/**
* Server port
*/
port?: number;
/**
* Direct mongo connection options, these do not go on the connection string
*/
connectionOptions: mongo.MongoClientOptions = {};
/**
* Is using the SRV DNS record configuration
*/
srvRecord?: boolean;
/**
* Mongo client options
*/
options: mongo.MongoClientOptions = {};
/**
* Allow storage modification at runtime
*/
modifyStorage?: boolean;
/**
* Frequency of culling for cullable content
*/
cullRate?: number | TimeSpan;
/**
* Connection string
*/
connectionString?: string;
/**
* Should we store the _id as a string in the id field
*/
storeId?: boolean;
/**
* Load all the ssl certs as needed
*/
async postConstruct(): Promise<void> {
const resolve = (file: string): Promise<string> => RuntimeResources.resolve(file).catch(() => file);
if (this.connectionString) {
const details = new URL(this.connectionString);
this.hosts ??= details.hostname.split(',').filter(host => !!host);
this.srvRecord ??= details.protocol === 'mongodb+srv:';
this.namespace ??= details.pathname.replace('/', '');
Object.assign(this.options, Object.fromEntries(details.searchParams.entries()));
this.port ??= +details.port;
this.username ??= details.username;
this.password ??= details.password;
}
// Defaults
if (!this.namespace) {
this.namespace = 'app';
}
if (!this.port || Number.isNaN(this.port)) {
this.port = 27017;
}
if (!this.hosts || !this.hosts.length) {
this.hosts = ['localhost'];
}
const options = this.options;
if (options.ssl) {
if (options.cert) {
options.cert = await Promise.all([options.cert].flat(2).map(data => Buffer.isBuffer(data) ? data : resolve(data)));
}
if (options.tlsCertificateKeyFile) {
options.tlsCertificateKeyFile = await resolve(options.tlsCertificateKeyFile);
}
if (options.tlsCAFile) {
options.tlsCAFile = await resolve(options.tlsCAFile);
}
if (options.tlsCRLFile) {
options.tlsCRLFile = await resolve(options.tlsCRLFile);
}
}
if (!Runtime.production) {
options.waitQueueTimeoutMS = 0;
options.serverSelectionTimeoutMS = TimeUtil.asMillis(1, 's');
}
}
/**
* Build connection URLs
*/
get url(): string {
const hosts = this.hosts!
.map(host => (this.srvRecord || host.includes(':')) ? host : `${host}:${this.port ?? 27017}`)
.join(',');
const optionString = new URLSearchParams(Object.entries(this.options)).toString();
let creds = '';
if (this.username) {
creds = `${[this.username, this.password].filter(part => !!part).join(':')}@`;
}
const url = `mongodb${this.srvRecord ? '+srv' : ''}://${creds}${hosts}/${this.namespace}?${optionString}`;
return url;
}
}