From a8f1d550785f736c377451980db18b5c25d19add Mon Sep 17 00:00:00 2001 From: xwashere Date: Mon, 6 Nov 2023 12:56:21 -0500 Subject: [PATCH] mongoo --- backend/UserConfig.ts | 10 +- backend/app.ts | 4 + backend/data.ts | 1 + backend/routers/api.ts | 4 + backend/sql/mongodb.ts | 238 ++++++++++++++++++++++++++++++++++++++++ backend/sql/postgres.ts | 3 +- common/types.d.ts | 12 +- frontend/setup.mts | 22 +++- package.json | 1 + pnpm-lock.yaml | 144 ++++++++++++++++++++++++ views/setup.pug | 14 +++ 11 files changed, 443 insertions(+), 10 deletions(-) create mode 100644 backend/sql/mongodb.ts diff --git a/backend/UserConfig.ts b/backend/UserConfig.ts index 735088c..a6b90ef 100644 --- a/backend/UserConfig.ts +++ b/backend/UserConfig.ts @@ -1,4 +1,4 @@ -import { UserConfiguration, UserConfigTypeChecker, PostgresConfiguration } from 'ass'; +import { UserConfiguration, UserConfigTypeChecker, PostgresConfiguration, MongoDBConfiguration } from 'ass'; import fs from 'fs-extra'; import { path } from '@tycrek/joint'; @@ -108,15 +108,15 @@ export class UserConfig { // * Optional database config(s) if (config.database != null) { // these both have the same schema so we can just check both - if (config.database.kind == 'mysql' || config.database.kind == 'postgres') { + if (config.database.kind == 'mysql' || config.database.kind == 'postgres' || config.database.kind == 'mongodb') { if (config.database.options != undefined) { if (!Checkers.sql.mySql.host(config.database.options.host)) throw new Error('Invalid database host'); if (!Checkers.sql.mySql.user(config.database.options.user)) throw new Error('Invalid databse user'); if (!Checkers.sql.mySql.password(config.database.options.password)) throw new Error('Invalid database password'); if (!Checkers.sql.mySql.database(config.database.options.database)) throw new Error('Invalid database'); - if (config.database.kind == 'postgres') { - if (!Checkers.sql.postgres.port((config.database.options as PostgresConfiguration).port)) { - throw new Error("Invalid database port"); + if (config.database.kind == 'postgres' || config.database.kind == 'mongodb') { + if (!Checkers.sql.postgres.port((config.database.options as PostgresConfiguration | MongoDBConfiguration).port)) { + throw new Error('Invalid database port'); } } } else throw new Error('Database options missing'); diff --git a/backend/app.ts b/backend/app.ts index 85165c8..6f3ac5d 100644 --- a/backend/app.ts +++ b/backend/app.ts @@ -16,6 +16,7 @@ import { MySQLDatabase } from './sql/mysql'; import { buildFrontendRouter } from './routers/_frontend'; import { DBManager } from './sql/database'; import { PostgreSQLDatabase } from './sql/postgres'; +import { MongoDBDatabase } from './sql/mongodb'; /** * Top-level metadata exports @@ -127,6 +128,9 @@ async function main() { case 'postgres': await DBManager.use(new PostgreSQLDatabase()); break; + case 'mongodb': + await DBManager.use(new MongoDBDatabase()); + break; } } catch (err) { throw new Error(`Failed to configure SQL`); } } else { // default to json database diff --git a/backend/data.ts b/backend/data.ts index 72e2f8c..a4c0603 100644 --- a/backend/data.ts +++ b/backend/data.ts @@ -26,6 +26,7 @@ const PATHS = { const DBNAMES = { 'mysql': 'MySQL', 'postgres': 'PostgreSQL', + 'mongodb': 'MongoDB', 'json': 'JSON' }; diff --git a/backend/routers/api.ts b/backend/routers/api.ts index e2aa2bc..43b5023 100644 --- a/backend/routers/api.ts +++ b/backend/routers/api.ts @@ -12,6 +12,7 @@ import { DBManager } from '../sql/database'; import { JSONDatabase } from '../sql/json'; import { MySQLDatabase } from '../sql/mysql'; import { PostgreSQLDatabase } from '../sql/postgres'; +import { MongoDBDatabase } from '../sql/mongodb'; const router = Router({ caseSensitive: true }); @@ -41,6 +42,9 @@ router.post('/setup', BodyParserJson(), async (req, res) => { case 'postgres': await DBManager.use(new PostgreSQLDatabase()); break; + case 'mongodb': + await DBManager.use(new MongoDBDatabase()); + break; } } diff --git a/backend/sql/mongodb.ts b/backend/sql/mongodb.ts new file mode 100644 index 0000000..ca8c258 --- /dev/null +++ b/backend/sql/mongodb.ts @@ -0,0 +1,238 @@ +import { AssFile, AssUser, MongoDBConfiguration, NID, UploadToken } from 'ass'; +import { UserConfig } from '../UserConfig'; +import { Database, DatabaseTable, DatabaseValue } from './database'; +import mongoose, { Model, Mongoose, Schema } from 'mongoose'; +import { log } from '../log'; + +interface TableVersion { + name: string; + version: number; +} + +const VERSIONS_SCHEMA = new Schema({ + name: String, + version: Number +}); + +interface MongoSchema { + id: NID, + data: T +} + +const FILE_SCHEMA = new Schema>({ + id: String, + data: { + fakeid: String, + fileKey: String, + filename: String, + mimetype: String, + save: { + local: String, + s3: Boolean // this will break if it gets the url object + // but im so fucking tired of this, were just + // going to keep it like this until it becomes + // a problem + }, + sha256: String, + size: Number, + timestamp: String, + uploader: String + } +}); + +const TOKEN_SCHEMA = new Schema>({ + id: String, + data: { + id: String, + token: String, + hint: String + } +}); + +const USER_SCHEMA = new Schema>({ + id: String, + data: { + id: String, + username: String, + password: String, + admin: Boolean, + tokens: [ String ], + files: [ String ], + meta: { + type: String, + get: (v: string) => JSON.parse(v), + set: (v: string) => JSON.stringify(v) + } + } +}); + +/** + * database adapter for mongodb + */ +export class MongoDBDatabase implements Database { + private _client: Mongoose; + + // mongoose models + private _versionModel: Model; + private _fileModel: Model>; + private _tokenModel: Model>; + private _userModel: Model>; + + private _validateConfig(): string | undefined { + // make sure the configuration exists + if (!UserConfig.ready) return 'User configuration not ready'; + if (typeof UserConfig.config.database != 'object') return 'MongoDB configuration missing'; + if (UserConfig.config.database.kind != 'mongodb') return 'Database not set to MongoDB, but MongoDB is in use, something has gone terribly wrong'; + if (typeof UserConfig.config.database.options != 'object') return 'MongoDB configuration missing'; + + let config = UserConfig.config.database.options; + + // check the postgres config + const checker = (val: string) => val != null && val !== ''; + const issue = + !checker(config.host) ? 'Missing MongoDB Host' + : !checker(config.user) ? 'Missing MongoDB User' + : !checker(config.password) ? 'Missing MongoDB Password' + : !checker(config.database) ? 'Missing MongoDB Database' + // ! Blame VS Code for this weird indentation + : undefined; + + return issue; + } + + open(): Promise { + return new Promise(async (resolve, reject) => { + try { + // validate config + let configError = this._validateConfig(); + if (configError != null) throw new Error(configError); + + let options = UserConfig.config.database!.options! as MongoDBConfiguration; + + // connect + log.info('MongoDB', `connecting to ${options.host}:${options.port}`); + this._client = await mongoose.connect(`mongodb://${options.user}:${options.password}@${options.host}:${options.port}/${options.database}`); + log.success('MongoDB', 'ok'); + + resolve(); + } catch (err) { + log.error('MongoDB', 'failed to connect'); + console.error(err); + reject(err); + } + }); + } + + close(): Promise { + return new Promise(async (resolve, reject) => { + try { + // gracefully disconnect + await this._client.disconnect(); + + resolve(); + } catch (err) { + log.error('MongoDB', 'failed to disconnect'); + console.error(err); + reject(err); + } + }); + } + + configure(): Promise { + return new Promise(async (resolve, reject) => { + try { + this._versionModel = this._client.model('assversions', VERSIONS_SCHEMA); + this._fileModel = this._client.model('assfiles', FILE_SCHEMA); + this._tokenModel = this._client.model('asstokens', TOKEN_SCHEMA); + this._userModel = this._client.model('assusers', USER_SCHEMA); + + // theres only one version right now so we dont need to worry about anything, just adding the version thingies if they arent there + let versions = await this._versionModel.find().exec() + .then(res => res.reduce((obj, doc) => obj.set(doc.name, doc.version), new Map())); + + for (let [table, version] of [['assfiles', 1], ['asstokens', 1], ['assusers', 1]] as [string, number][]) { + if (!versions.has(table)) { + // set the version + new this._versionModel({ + name: table, + version: version + }).save(); + + versions.set(table, version); + } + } + + resolve(); + } catch (err) { + log.error('MongoDB', 'failed to configure'); + console.error(err); + reject(err); + } + }); + } + + put(table: DatabaseTable, key: string, data: DatabaseValue): Promise { + return new Promise(async (resolve, reject) => { + try { + const models = { + assfiles: this._fileModel, + assusers: this._userModel, + asstokens: this._tokenModel + }; + + await new models[table]({ + id: key, + data: data + }).save(); + + resolve(); + } catch (err) { + reject(err); + } + }); + } + + get(table: DatabaseTable, key: string): Promise { + return new Promise(async (resolve, reject) => { + try { + const models = { + assfiles: this._fileModel, + assusers: this._userModel, + asstokens: this._tokenModel + }; + + // @ts-ignore + // typescript cant infer this but it is 100% correct + // no need to worry :> + let result = await models[table].find({ + id: key + }).exec(); + + resolve(result.length ? result[0].data : void 0); + } catch (err) { + reject(err); + } + }); + } + + getAll(table: DatabaseTable): Promise<{ [index: string]: DatabaseValue; }> { + return new Promise(async (resolve, reject) => { + try { + const models = { + assfiles: this._fileModel, + assusers: this._userModel, + asstokens: this._tokenModel + }; + + // more ts-ignore! + // @ts-ignore + let result = await models[table].find({}).exec() // @ts-ignore + .then(res => res.reduce((obj, doc) => (obj[doc.id] = doc.data, obj), {})); + + resolve(result); + } catch (err) { + reject(err); + } + }); + } +}; \ No newline at end of file diff --git a/backend/sql/postgres.ts b/backend/sql/postgres.ts index 7b879f7..35d4719 100644 --- a/backend/sql/postgres.ts +++ b/backend/sql/postgres.ts @@ -19,7 +19,7 @@ export class PostgreSQLDatabase implements Database { // make sure the configuration exists if (!UserConfig.ready) return 'User configuration not ready'; if (typeof UserConfig.config.database != 'object') return 'PostgreSQL configuration missing'; - if (UserConfig.config.database.kind != "postgres") return 'Database not set to PostgreSQL, but PostgreSQL is in use, something has gone terribly wrong'; + if (UserConfig.config.database.kind != 'postgres') return 'Database not set to PostgreSQL, but PostgreSQL is in use, something has gone terribly wrong'; if (typeof UserConfig.config.database.options != 'object') return 'PostgreSQL configuration missing'; let config = UserConfig.config.database.options; @@ -35,7 +35,6 @@ export class PostgreSQLDatabase implements Database { : undefined; return issue; - } public open(): Promise { diff --git a/common/types.d.ts b/common/types.d.ts index ddc3cd8..fa3a5a5 100644 --- a/common/types.d.ts +++ b/common/types.d.ts @@ -52,8 +52,8 @@ declare module 'ass' { } interface DatabaseConfiguration { - kind: 'mysql' | 'postgres' | 'json'; - options?: MySQLConfiguration | PostgresConfiguration; + kind: 'mysql' | 'postgres' | 'json' | 'mongodb'; + options?: MySQLConfiguration | PostgresConfiguration | MongoDBConfiguration; } interface MySQLConfiguration { @@ -71,6 +71,14 @@ declare module 'ass' { database: string; } + interface MongoDBConfiguration { + host: string; + port: number; + user: string; + password: string; + database: string; + } + /** * rate limiter configuration * @since 0.15.0 diff --git a/frontend/setup.mts b/frontend/setup.mts index c4372d8..18357e0 100644 --- a/frontend/setup.mts +++ b/frontend/setup.mts @@ -56,6 +56,13 @@ document.addEventListener('DOMContentLoaded', () => { pgsqlPassword: document.querySelector('#pgsql-password') as SlInput, pgsqlDatabase: document.querySelector('#pgsql-database') as SlInput, + mongoDBTab: document.querySelector('#mongodb-tab') as SlTab, + mongoDBHost: document.querySelector('#mongodb-host') as SlInput, + mongoDBPort: document.querySelector('#mongodb-port') as SlInput, + mongoDBUser: document.querySelector('#mongodb-user') as SlInput, + mongoDBPassword: document.querySelector('#mongodb-password') as SlInput, + mongoDBDatabase: document.querySelector('#mongodb-database') as SlInput, + userUsername: document.querySelector('#user-username') as SlInput, userPassword: document.querySelector('#user-password') as SlInput, @@ -127,7 +134,20 @@ document.addEventListener('DOMContentLoaded', () => { database: Elements.pgsqlDatabase.value } } - }; + } + } else if (Elements.mongoDBTab.active) { + if (Elements.mongoDBHost.value != null && Elements.mongoDBHost.value != '') { + config.database = { + kind: 'mongodb', + options: { + host: Elements.mongoDBHost.value, + port: parseInt(Elements.mongoDBPort.value), + user: Elements.mongoDBUser.value, + password: Elements.mongoDBPassword.value, + database: Elements.mongoDBDatabase.value + } + } + } } // append rate limit config, if specified diff --git a/package.json b/package.json index d4b7dd0..f08f7d9 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "fs-extra": "^11.1.1", "luxon": "^3.4.3", "memorystore": "^1.6.7", + "mongoose": "^8.0.0", "mysql2": "^3.6.2", "node-vibrant": "^3.1.6", "pg": "^8.11.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 30d02e7..2fb2b40 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -71,6 +71,9 @@ dependencies: memorystore: specifier: ^1.6.7 version: 1.6.7 + mongoose: + specifier: ^8.0.0 + version: 8.0.0 mysql2: specifier: ^3.6.2 version: 3.6.2 @@ -1205,6 +1208,12 @@ packages: - supports-color dev: false + /@mongodb-js/saslprep@1.1.1: + resolution: {integrity: sha512-t7c5K033joZZMspnHg/gWPE4kandgc2OxE74aYOtGKfgB9VPuVJPix0H6fhmm2erj5PBJ21mqcx34lpIGtUCsQ==} + dependencies: + sparse-bitfield: 3.0.3 + dev: false + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1930,6 +1939,17 @@ packages: resolution: {integrity: sha512-I3pkr8j/6tmQtKV/ZzHtuaqYSQvyjGRKH4go60Rr0IDLlFxuRT5V32uvB1mecM5G1EVAUyF/4r4QZ1GHgz+mxA==} dev: false + /@types/webidl-conversions@7.0.2: + resolution: {integrity: sha512-uNv6b/uGRLlCVmelat2rA8bcVd3k/42mV2EmjhPh6JLkd35T5bgwR/t6xy7a9MWhd9sixIeBUzhBenvk3NO+DQ==} + dev: false + + /@types/whatwg-url@8.2.2: + resolution: {integrity: sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==} + dependencies: + '@types/node': 20.8.9 + '@types/webidl-conversions': 7.0.2 + dev: false + /@xoi/gps-metadata-remover@1.1.2(@babel/core@7.23.2): resolution: {integrity: sha512-QeGcEvlesS+cXwfao14kdLI2zHJk3vppKSEbpbiNP1abx45P8HWqGEWhgF71bKlnCSW8a7b4RNDNa4mj1aHPMA==} dependencies: @@ -2190,6 +2210,11 @@ packages: update-browserslist-db: 1.0.13(browserslist@4.22.1) dev: false + /bson@6.2.0: + resolution: {integrity: sha512-ID1cI+7bazPDyL9wYy9GaQ8gEEohWvcUl/Yf0dIdutJxnmInEEyCsb4awy/OiBfall7zBA179Pahi3vCdFze3Q==} + engines: {node: '>=16.20.1'} + dev: false + /buffer-equal@0.0.1: resolution: {integrity: sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA==} engines: {node: '>=0.4.0'} @@ -3344,6 +3369,11 @@ packages: promise: 7.3.1 dev: false + /kareem@2.5.1: + resolution: {integrity: sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==} + engines: {node: '>=12.0.0'} + dev: false + /lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} @@ -3459,6 +3489,10 @@ packages: engines: {node: '>= 0.6'} dev: false + /memory-pager@1.5.0: + resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==} + dev: false + /memorystore@1.6.7: resolution: {integrity: sha512-OZnmNY/NDrKohPQ+hxp0muBcBKrzKNtHr55DbqSx9hLsYVNnomSAMRAtI7R64t3gf3ID7tHQA7mG4oL3Hu9hdw==} engines: {node: '>=0.10'} @@ -3567,6 +3601,81 @@ packages: hasBin: true dev: false + /mongodb-connection-string-url@2.6.0: + resolution: {integrity: sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==} + dependencies: + '@types/whatwg-url': 8.2.2 + whatwg-url: 11.0.0 + dev: false + + /mongodb@6.2.0: + resolution: {integrity: sha512-d7OSuGjGWDZ5usZPqfvb36laQ9CPhnWkAGHT61x5P95p/8nMVeH8asloMwW6GcYFeB0Vj4CB/1wOTDG2RA9BFA==} + engines: {node: '>=16.20.1'} + peerDependencies: + '@aws-sdk/credential-providers': ^3.188.0 + '@mongodb-js/zstd': ^1.1.0 + gcp-metadata: ^5.2.0 + kerberos: ^2.0.1 + mongodb-client-encryption: '>=6.0.0 <7' + snappy: ^7.2.2 + socks: ^2.7.1 + peerDependenciesMeta: + '@aws-sdk/credential-providers': + optional: true + '@mongodb-js/zstd': + optional: true + gcp-metadata: + optional: true + kerberos: + optional: true + mongodb-client-encryption: + optional: true + snappy: + optional: true + socks: + optional: true + dependencies: + '@mongodb-js/saslprep': 1.1.1 + bson: 6.2.0 + mongodb-connection-string-url: 2.6.0 + dev: false + + /mongoose@8.0.0: + resolution: {integrity: sha512-PzwkLgm1Jhj0NQdgGfnFsu0QP9V1sBFgbavEgh/IPAUzKAagzvEhuaBuAQOQGjczVWnpIU9tBqyd02cOTgsPlA==} + engines: {node: '>=16.20.1'} + dependencies: + bson: 6.2.0 + kareem: 2.5.1 + mongodb: 6.2.0 + mpath: 0.9.0 + mquery: 5.0.0 + ms: 2.1.3 + sift: 16.0.1 + transitivePeerDependencies: + - '@aws-sdk/credential-providers' + - '@mongodb-js/zstd' + - gcp-metadata + - kerberos + - mongodb-client-encryption + - snappy + - socks + - supports-color + dev: false + + /mpath@0.9.0: + resolution: {integrity: sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==} + engines: {node: '>=4.0.0'} + dev: false + + /mquery@5.0.0: + resolution: {integrity: sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==} + engines: {node: '>=14.0.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + /ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} dev: false @@ -4466,6 +4575,11 @@ packages: resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} dev: false + /punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + dev: false + /qr-creator@1.0.0: resolution: {integrity: sha512-C0cqfbS1P5hfqN4NhsYsUXePlk9BO+a45bAQ3xLYjBL3bOIFzoVEjs79Fado9u9BPBD3buHi3+vY+C8tHh4qMQ==} dev: false @@ -4716,6 +4830,10 @@ packages: object-inspect: 1.13.1 dev: false + /sift@16.0.1: + resolution: {integrity: sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==} + dev: false + /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} dev: false @@ -4743,6 +4861,12 @@ packages: engines: {node: '>=0.10.0'} dev: false + /sparse-bitfield@3.0.3: + resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==} + dependencies: + memory-pager: 1.5.0 + dev: false + /split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} @@ -5007,6 +5131,13 @@ packages: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} dev: false + /tr46@3.0.0: + resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} + engines: {node: '>=12'} + dependencies: + punycode: 2.3.1 + dev: false + /ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} dev: false @@ -5131,6 +5262,19 @@ packages: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} dev: false + /webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + dev: false + + /whatwg-url@11.0.0: + resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} + engines: {node: '>=12'} + dependencies: + tr46: 3.0.0 + webidl-conversions: 7.0.0 + dev: false + /whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} dependencies: diff --git a/views/setup.pug b/views/setup.pug index 5426e4e..9758cb8 100644 --- a/views/setup.pug +++ b/views/setup.pug @@ -65,6 +65,20 @@ block content h3.setup-text-item-title Database sl-input#pgsql-database(type='text' placeholder='assdb' clearable): sl-icon(slot='prefix' name='fas-database' library='fa') + //- * MongoDB + sl-tab#mongodb-tab(slot='nav' panel='mongodb') MongoDB + sl-tab-panel(name='mongodb') + h3.setup-text-item-title Host + sl-input#mongodb-host(type='text' placeholder='mongo.example.com' clearable): sl-icon(slot='prefix' name='fas-server' library='fa') + h3.setup-text-item-title Port + sl-input#mongodb-port(type='number' placeholder='27017' min='1' max='65535' no-spin-buttons clearable): sl-icon(slot='prefix' name='fas-number' library='fa') + h3.setup-text-item-title User + sl-input#mongodb-user(type='text' placeholder='mongo' clearable): sl-icon(slot='prefix' name='fas-user' library='fa') + h3.setup-text-item-title Password + sl-input#mongodb-password(type='password' placeholder='super-secure' clearable): sl-icon(slot='prefix' name='fas-lock' library='fa') + h3.setup-text-item-title Database + sl-input#mongodb-database(type='text' placeholder='assdb' clearable): sl-icon(slot='prefix' name='fas-database' library='fa') + //- * S3 h2.setup-text-section-header.mt-4 S3 #[span.setup-text-optional optional] .setup-panel