Initial commit
This commit is contained in:
commit
9277a804bb
18 changed files with 851 additions and 0 deletions
33
src/entity/Chart.ts
Normal file
33
src/entity/Chart.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import { Entity, BaseEntity, PrimaryColumn, Column, OneToMany, ManyToOne, Relation } from 'typeorm';
|
||||
|
||||
/** Represents a Helm Chart */
|
||||
@Entity("Charts")
|
||||
export class Chart extends BaseEntity {
|
||||
/** The unique ID of the Helm Chart */
|
||||
@PrimaryColumn()
|
||||
id!: string;
|
||||
|
||||
/** When the Helm Chart was pushed/created */
|
||||
@Column()
|
||||
created!: Date;
|
||||
|
||||
/** The user that pushed the Helm Chart (operator from Harbor webhook) */
|
||||
@Column()
|
||||
user!: string;
|
||||
|
||||
/** Helm Chart Name */
|
||||
@Column()
|
||||
name!: string;
|
||||
|
||||
/** Helm chart digest */
|
||||
@Column()
|
||||
digest!: string;
|
||||
|
||||
/** Helm chart tag */
|
||||
@Column()
|
||||
tag!: string;
|
||||
|
||||
/** Helm Chart URL */
|
||||
@Column()
|
||||
url!: string;
|
||||
}
|
||||
145
src/pages/base.ejs
Normal file
145
src/pages/base.ejs
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<% if(typeof description !== 'undefined') { %>
|
||||
<%# If the description is explicitly set use it %>
|
||||
<meta name="description" content="<%= description %>">
|
||||
<% } else if(typeof company !== 'undefined') { %>
|
||||
<%# If the description isn't explicitly set but the company name is (company variable) then assume this a generic company Helm chart repository and set the description as such %>
|
||||
<meta name="description" content="<% if(typeof company !== 'undefined') { %><%= company %> <% } %> Helm Repository">
|
||||
<% } %>
|
||||
<% if (typeof keywords !== 'undefined') { %>
|
||||
<%# If the keywords are explicitly set use them %>
|
||||
<meta name="keywords" content="<%= keywords %>">
|
||||
<% } else { %>
|
||||
<%# If the keywords aren't explicitly set then use the default keywords %>
|
||||
<meta name="keywords" content="helm, kubernetes, repository, charts, <% if(typeof company !== 'undefined') { %><%= company %> <% } %>">
|
||||
<% } %>
|
||||
<% if (typeof author !== 'undefined') { %>
|
||||
<%# If the author is explicitly set use it %>
|
||||
<meta name="author" content="<%= author %>">
|
||||
<% } else if (typeof company !== 'undefined') { %>
|
||||
<%# If the author isn't explicitly set but the company name is (company variable) then use it as the author %>
|
||||
<meta name="author" content="<%= company %>">
|
||||
<% } %>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<% if(typeof title !== 'undefined' && title.length > 0) { %>
|
||||
<title><% if (typeof titlePrefix !== 'undefined') { %><%= titlePrefix %><% } %><%= title %><% if (typeof titleSuffix !== 'undefined') { %><%= titleSuffix %><% } %></title>
|
||||
<% } %>
|
||||
<!-- Styles -->
|
||||
<!-- Custom styling -->
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<link rel="stylesheet" type="text/css" href="/css/accessibility.css">
|
||||
<%# <!-- Foundation Framework --> %>
|
||||
<%# <link rel="stylesheet" href="/css/app.css"> %>
|
||||
<%# <!-- SASS components --> %>
|
||||
<%# <link rel="stylesheet" type="text/css" href="/css/components/system-themed-background.css"> %>
|
||||
<!-- Controller specific styling -->
|
||||
<%# Add any additional stylesheets specified within a controller etc... %>
|
||||
<%# This can either be a singular string or a array of strings %>
|
||||
<%# Note, that the string should be the name of the stylesheet WITHOUT the `.css` extension and exist in the `css/` directory %>
|
||||
<% if (typeof extraStyles !== 'undefined') { %>
|
||||
<% if (Array.isArray(extraStyles)) { %>
|
||||
<%# Because it's an array, we need to loop through each stylesheet and include it %>
|
||||
<% for (let style of extraStyles) { %>
|
||||
<link rel="stylesheet" type="text/css" href="/css/<%= style %>.css">
|
||||
<% } %>
|
||||
<% } else { %>
|
||||
<%# Include the singular stylesheet %>
|
||||
<link rel="stylesheet" type="text/css" href="/css/<%= extraStyles %>.css">
|
||||
<% } %>
|
||||
<% } %>
|
||||
<!-- Scripts -->
|
||||
<!-- Third-party scripts -->
|
||||
<%# <script src="https://js.stripe.com/v3" async></script> %>
|
||||
<%# <script src="https://kit.fontawesome.com/c754d91c7e.js" crossorigin="anonymous"></script> %>
|
||||
<%# <!-- Foundation Framework --> %>
|
||||
<%# <script type="application/javascript" src="/js/foundation/main.js" defer></script> %>
|
||||
<!-- Controller specific scripts -->
|
||||
<%# Add any additional scripts specified within a controller etc... %>
|
||||
<%# %>
|
||||
<%# Note, that these can come in multiple formats as described in the table below: %>
|
||||
<%# | Type | Description | Format | Use Cases | %>
|
||||
<%# | ------ | --------------------------------------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------- | %>
|
||||
<%# | string | The name of the script to include | `<script name>` | Simple include of the script | %>
|
||||
<%# | object | An object about the script to include | `{ script: '<script name>', defer: <true/false> }` | Being more explicit about script's properties (ex. defer vs. async, etc...) | %>
|
||||
<%# | array | An array of strings or objects (as described above) | `[ '<script name>', { script: '<script name>', defer: <true/false> } ]` | Include multiple scripts | %>
|
||||
<%# %>
|
||||
<%# The string or `.script` property of the object should be the script name WITHOUT the `.js` extension and exist in the `js/` directory if it's a "local" script. %>
|
||||
<%# Or should be the full URL if it's a "external" script %>
|
||||
<% if (typeof extraScripts !== 'undefined') { %>
|
||||
<% if (Array.isArray(extraScripts)) { %>
|
||||
<%# Because it's an array, we need to loop through each script and include it %>
|
||||
<% for (let script of extraScripts) { %>
|
||||
<% if(typeof script === 'object') { %>
|
||||
<%# Because the current array items is an object we use the `.script` and `.defer` properties to include it %>
|
||||
<% if(script.script.startsWith('http') || script.script.startsWith('https')) { %>
|
||||
<%# Because the `.script` property starts with `http` or `https` we assume it's an "external" script and include it as a straight URL %>
|
||||
<script type="application/javascript" src="<%= script.script %>" <% if(script.defer) { %>defer<% } %>></script>
|
||||
<% } else { %>
|
||||
<%# Because the `.script` property doesn't start with `http` or `https` we assume it's a "local" script and include it as a local script (from the `js/` folder and with a `.js` extension) %>
|
||||
<script type="application/javascript" src="/js/<%= script.script %>.js" <% if(script.defer) { %>defer<% } %>></script>
|
||||
<% } %>
|
||||
<% } else { %>
|
||||
<% if(script.startsWith('http') || script.startsWith('https')) { %>
|
||||
<%# Because the string starts with `http` or `https` we assume it's an "external" script and include it as a straight URL %>
|
||||
<script type="application/javascript" src="<%= script %>"></script>
|
||||
<% } else { %>
|
||||
<%# Because the string doesn't start with `http` or `https` we assume it's a "local" script and include it as a local script (from the `js/` folder and with a `.js` extension) %>
|
||||
<script type="application/javascript" src="/js/<%= script %>.js" defer></script>
|
||||
<% } %>
|
||||
<% } %>
|
||||
<% } %>
|
||||
<% } else if (typeof extraScripts === 'object') { %>
|
||||
<% if(extraScripts.script.startsWith('http') || extraScripts.script.startsWith('https')) { %>
|
||||
<%# Because the `.script` property of the singular object starts with `http` or `https` we assume it's an "external" script and include it as a straight URL %>
|
||||
<script type="application/javascript" src="<%= extraScripts.script %>" <% if(extraScripts.defer) { %>defer<% } %>></script>
|
||||
<% } else { %>
|
||||
<%# Because the `.script` property of the singular object doesn't start with `http` or `https` we assume it's a "local" script and include it as a local script (from the `js/` folder and with a `.js` extension) %>
|
||||
<script type="application/javascript" src="/js/<%= extraScripts.script %>.js" <% if(extraScripts.defer) { %>defer<% } %>></script>
|
||||
<% } %>
|
||||
<% } else { %>
|
||||
<% if(extraScripts.startsWith('http') || extraScripts.startsWith('https')) { %>
|
||||
<%# Because the singular string starts with `http` or `https` we assume it's an "external" script and include it as a straight URL %>
|
||||
<script type="application/javascript" src="<%= extraScripts %>"></script>
|
||||
<% } else { %>
|
||||
<%# Because the singular string doesn't start with `http` or `https` we assume it's a "local" script and include it as a local script (from the `js/` folder and with a `.js` extension) %>
|
||||
<script type="application/javascript" src="/js/<%= extraScripts %>.js" defer></script>
|
||||
<% } %>
|
||||
<% } %>
|
||||
<% } %>
|
||||
</head>
|
||||
<body>
|
||||
<a id="skip-link" href="#main">Skip to main content</a>
|
||||
<div id="contents">
|
||||
<header>
|
||||
<% if(typeof header !== 'undefined') { %>
|
||||
<%# Because the controller has explicitly set the header, we use the specified header here (within the `<header></header>` tags) %>
|
||||
<%- include(header) %>
|
||||
<% } else { %>
|
||||
<%# Because no explicitly header was set use the default header %>
|
||||
<%- include('includes/header.ejs') %>
|
||||
<% } %>
|
||||
</header>
|
||||
<div style="width: 100%">
|
||||
<main id="main">
|
||||
<div class="container">
|
||||
<div class="content">
|
||||
<%- include(page) %>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
<% if(typeof footer !== 'undefined') { %>
|
||||
<%# Because the controller has explicitly set the footer, we use the specified footer here (within the `<footer></footer>` tags) %>
|
||||
<%- include(footer) %>
|
||||
<% } else { %>
|
||||
<%# Because no explicitly footer was set use the default footer %>
|
||||
<%- include('includes/footer.ejs') %>
|
||||
<% } %>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
0
src/pages/includes/footer.ejs
Normal file
0
src/pages/includes/footer.ejs
Normal file
0
src/pages/includes/header.ejs
Normal file
0
src/pages/includes/header.ejs
Normal file
13
src/pages/index.ejs
Normal file
13
src/pages/index.ejs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<h1>Welcome to the <%= company %> Helm Repository</h1>
|
||||
<p>
|
||||
To use this repository, you need to add it to your Helm client.
|
||||
</p>
|
||||
<pre>helm repo add <%= company.replaceAll(' ', '') %> https://<%= hostname %>/</pre>
|
||||
<p>
|
||||
Once you have added the repository, you can search for charts in the repository.
|
||||
</p>
|
||||
<pre>helm search repo <%= company.replaceAll(' ', '') %></pre>
|
||||
<p>
|
||||
To install a chart from the repository, use the following command.
|
||||
</p>
|
||||
<pre>helm install my-release <%= company.replaceAll(' ', '') %>/some-chart</pre>
|
||||
61
src/routes/HarborRoutes.ts
Normal file
61
src/routes/HarborRoutes.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import express, { Request, Response } from 'express';
|
||||
import { v4 as newUUID } from 'uuid';
|
||||
import { Controller, POST, BaseController } from '@BridgemanAccessible/ba-web-framework';
|
||||
|
||||
import { Chart } from '../entity/Chart';
|
||||
|
||||
type WebhookResponse = {
|
||||
type: 'PUSH_ARTIFACT' | 'DELETE_ARTIFACT',
|
||||
occur_at: number,
|
||||
operator: string,
|
||||
event_data: {
|
||||
resources: {
|
||||
digest: string,
|
||||
tag: string,
|
||||
resource_url: string
|
||||
}[],
|
||||
repository: {
|
||||
date_created?: number,
|
||||
name: string,
|
||||
namespace: string,
|
||||
repo_full_name: string,
|
||||
repo_type: string
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Controller()
|
||||
export class HarborRoutes extends BaseController {
|
||||
@POST('/harbor', express.json())
|
||||
async webhook(req: Request, res: Response) {
|
||||
const response: WebhookResponse = req.body;
|
||||
if(response.type === 'PUSH_ARTIFACT') {
|
||||
console.log('Pushed a new Helm Chart');
|
||||
|
||||
// Create a new database entry for the Helm Chart that got pushed
|
||||
await Chart.create({
|
||||
id: newUUID(),
|
||||
created: new Date(response.occur_at),
|
||||
user: response.operator,
|
||||
name: response.event_data.repository.name,
|
||||
digest: response.event_data.resources[0].digest,
|
||||
tag: response.event_data.resources[0].tag,
|
||||
url: response.event_data.resources[0].resource_url
|
||||
}).save();
|
||||
}
|
||||
else if(response.type === 'DELETE_ARTIFACT') {
|
||||
console.log('Deleted a Helm Chart');
|
||||
|
||||
// Delete the Helm Chart from the database
|
||||
Chart.delete({ digest: response.event_data.resources[0].digest });
|
||||
}
|
||||
console.log(`Happened At: ${response.occur_at}`);
|
||||
console.log(`User (Operator): ${response.operator}`);
|
||||
console.log(`Name: ${response.event_data.repository.name}`);
|
||||
console.log(`Digest: ${response.event_data.resources[0].digest}`);
|
||||
console.log(`Tag: ${response.event_data.resources[0].tag}`);
|
||||
console.log(`URL: ${response.event_data.resources[0].resource_url}`);
|
||||
|
||||
res.status(200).send('ok');
|
||||
}
|
||||
}
|
||||
63
src/routes/HelmRoutes.ts
Normal file
63
src/routes/HelmRoutes.ts
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import { Request, Response } from 'express';
|
||||
import { Controller, GET, BaseController } from '@BridgemanAccessible/ba-web-framework';
|
||||
import { dump as writeYAML } from 'js-yaml';
|
||||
|
||||
import { Chart } from '../entity/Chart';
|
||||
|
||||
type HelmRepoIndexEntry = {
|
||||
apiVersion: 'v1',
|
||||
appVersion: `${string}.${string}.${string}`,
|
||||
dependencies: {
|
||||
name: string,
|
||||
repository: string,
|
||||
version: `${string}.${string}.${string}`
|
||||
}[],
|
||||
description: string,
|
||||
digest: string,
|
||||
home: string,
|
||||
name: string,
|
||||
sources: string[],
|
||||
urls: string[],
|
||||
version: `${string}.${string}.${string}`
|
||||
};
|
||||
|
||||
type HelmRepoIndex = {
|
||||
apiVersion: 'v1',
|
||||
entries: {
|
||||
[key: string]: HelmRepoIndexEntry[]
|
||||
}
|
||||
};
|
||||
|
||||
@Controller()
|
||||
export class HelmRoutes extends BaseController {
|
||||
@GET('/index.yaml')
|
||||
private async index(req: Request, res: Response) {
|
||||
const index: HelmRepoIndex = {
|
||||
apiVersion: 'v1',
|
||||
entries: {}
|
||||
};
|
||||
|
||||
// Get all Helm Charts from the database and add them to the index
|
||||
const charts = await Chart.find();
|
||||
charts.forEach(chart => {
|
||||
index.entries[chart.name] = [
|
||||
{
|
||||
apiVersion: 'v1',
|
||||
appVersion: '1.0.0',
|
||||
dependencies: [],
|
||||
description: chart.name,
|
||||
digest: chart.digest,
|
||||
home: `https://${process.env.HOSTNAME}/${chart.url.substring(chart.url.indexOf('/', chart.url.indexOf('/') + 1) + 1, chart.url.indexOf(':'))}`,
|
||||
name: chart.name,
|
||||
sources: [],
|
||||
urls: [`oci://${chart.url}`],
|
||||
version: chart.tag as `${string}.${string}.${string}`
|
||||
}
|
||||
];
|
||||
})
|
||||
|
||||
res.status(200)
|
||||
.setHeader('Content-Type', 'application/yaml') // Per IANA Media Types listing as noted in [RFC 9512](https://datatracker.ietf.org/doc/html/rfc9512)
|
||||
.send(writeYAML(index));
|
||||
}
|
||||
}
|
||||
9
src/routes/HomeRoutes.ts
Normal file
9
src/routes/HomeRoutes.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { Request, Response } from 'express';
|
||||
import { Controller, GET, Page, BaseController } from '@BridgemanAccessible/ba-web-framework';
|
||||
|
||||
@Controller()
|
||||
export class HomeRoutes extends BaseController {
|
||||
@Page('Home', 'index.ejs')
|
||||
@GET('/')
|
||||
async home(req: Request, res: Response) {}
|
||||
}
|
||||
39
src/server.ts
Normal file
39
src/server.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import path from 'path';
|
||||
import { Application } from 'express';
|
||||
import { App, Initializer, globalTemplateValues } from '@BridgemanAccessible/ba-web-framework';
|
||||
|
||||
import { createConn } from './utils/db';
|
||||
|
||||
/**
|
||||
* Create the initial database connection
|
||||
*
|
||||
* This includes setting up the connection options and creating the connection itself.
|
||||
*/
|
||||
async function createInitialDatabaseConnection() {
|
||||
// Setup the database connection options
|
||||
const connOptions = {
|
||||
synchronize: process.env.NODE_ENV !== 'production',
|
||||
logging: process.env.NODE_ENV !== 'production'
|
||||
}
|
||||
|
||||
// Create a connection to the database
|
||||
await createConn('postgres', connOptions);
|
||||
}
|
||||
|
||||
async function onStart(app: Application) {
|
||||
// Create the initial database connection
|
||||
createInitialDatabaseConnection();
|
||||
}
|
||||
|
||||
async function main() {
|
||||
await new App().run(new Initializer({
|
||||
controllersPath: path.join(__dirname, 'routes'),
|
||||
staticFilesPath: path.join(__dirname, 'static'),
|
||||
view: {
|
||||
engine: 'ejs',
|
||||
filesPath: path.join(__dirname, 'pages')
|
||||
}
|
||||
}, globalTemplateValues({ company: process.env.COMPANY, titleSuffix: process.env.WEBSITE_TITLE_SUFFIX, hostname: process.env.HOSTNAME })), onStart);
|
||||
}
|
||||
|
||||
main()
|
||||
28
src/static/css/accessibility.css
Normal file
28
src/static/css/accessibility.css
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/* Style for the "skip to content" link found at the top of the page */
|
||||
#skip-link {
|
||||
position: absolute;
|
||||
top: -40px;
|
||||
left: 0;
|
||||
background: #fff;
|
||||
color: #000;
|
||||
padding: 8px;
|
||||
z-index: 100;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/* Style to visually show the "skip to content" link when keyboard has focus */
|
||||
#skip-link:focus {
|
||||
top: 0;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* For elements that should be hidden visually bt NOT from screen readers */
|
||||
/* Ex. input form labels that are labeled differently visually */
|
||||
.visually-hidden {
|
||||
position: absolute;
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
overflow: hidden;
|
||||
clip: rect(1px, 1px, 1px, 1px);
|
||||
white-space: nowrap;
|
||||
}
|
||||
87
src/static/css/style.css
Normal file
87
src/static/css/style.css
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
:root {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
html, body {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
/*font-family: 'Arial', sans-serif;
|
||||
font-size: 14pt;
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;*/
|
||||
}
|
||||
|
||||
main {
|
||||
min-height: 100%;
|
||||
padding-top: 5px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
padding-bottom: 60px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/*#contents {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#contents #sidebar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 384px;
|
||||
min-height: 100vh;
|
||||
background-color: #C2C2C2;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
#contents #sidebar button:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#contents #sidebar button:hover,
|
||||
#contents #sidebar button:focus,
|
||||
#contents #sidebar a:hover,
|
||||
#contents #sidebar a:focus {
|
||||
background-color: #000000;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
#contents #sidebar hr {
|
||||
background-color: #000000;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
#contents main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
padding: 10px 20px;
|
||||
background-color: #C2C2C2;
|
||||
color: #000000;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #000000;
|
||||
}
|
||||
|
||||
.btn-panel {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20px;
|
||||
}*/
|
||||
82
src/utils/db.ts
Normal file
82
src/utils/db.ts
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
import path from 'path';
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
/**
|
||||
* Creates a connection to the database.
|
||||
*
|
||||
* @param kwargs Other keyword arguments to pass to the TypeORM DataSource. (ex. { logging: true })
|
||||
* @returns A connection to the database.
|
||||
*/
|
||||
async function createPostgreSQLConn(kwargs: object): Promise<DataSource> {
|
||||
// Parse the database connection information from the environment variables
|
||||
const DB_HOST = process.env.DB_HOST;
|
||||
const DB_PORT: number = typeof process.env.DB_PORT !== 'undefined' ? parseInt(process.env.DB_PORT) : 5432;
|
||||
const DB_USER = process.env.DB_USER || 'postgres';
|
||||
const DB_PASSWORD = process.env.DB_PASSWORD || 'db_password';
|
||||
const DB_NAME = process.env.DB_NAME || 'db';
|
||||
|
||||
console.log(`Attempting to connect to ${DB_HOST} at port ${DB_PORT} on database ${DB_NAME} as ${DB_USER} with password ${DB_PASSWORD}`);
|
||||
|
||||
// Create the connection
|
||||
return new DataSource({
|
||||
type: "postgres",
|
||||
host: DB_HOST,
|
||||
port: DB_PORT,
|
||||
username: DB_USER,
|
||||
password: DB_PASSWORD,
|
||||
database: DB_NAME,
|
||||
//ssl: process.env.NODE_ENV === 'production' ? true : false,
|
||||
...kwargs,
|
||||
entities: [
|
||||
path.resolve(__dirname, '../', './entity/**/*.ts'),
|
||||
path.resolve(__dirname, '../', './entity/**/*.js')
|
||||
]
|
||||
}).initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a connection to the SQLite database.
|
||||
*
|
||||
* @param kwargs Other keyword arguments to pass to the TypeORM DataSource. (ex. { logging: true })
|
||||
* @returns The connection to the database.
|
||||
*/
|
||||
async function createSQLiteConn(kwargs: object): Promise<DataSource> {
|
||||
// Parse the database connection information from the environment variables
|
||||
const DB_NAME = process.env.DATABASE_FILE || 'database.sqlite';
|
||||
|
||||
console.log(`Attempting to connect to ${DB_NAME}`);
|
||||
|
||||
// Create the connection
|
||||
return new DataSource({
|
||||
type: "sqlite",
|
||||
database: DB_NAME,
|
||||
...kwargs,
|
||||
entities: [
|
||||
path.resolve(__dirname, '../', './entity/**/*.ts'),
|
||||
path.resolve(__dirname, '../', './entity/**/*.js')
|
||||
]
|
||||
}).initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* The types of databases that can be connected to.
|
||||
*/
|
||||
type DBTypes = 'sqlite' | 'postgres';
|
||||
|
||||
/**
|
||||
* Creates a connection to the database.
|
||||
*
|
||||
* @param kwargs The keyword arguments to pass to the TypeORM DataSource. (ex. { logging: true })
|
||||
* @returns The connection to the database.
|
||||
*/
|
||||
export async function createConn(dbType: DBTypes, kwargs: object): Promise<DataSource> {
|
||||
// Return the connection based on the database type
|
||||
switch(dbType) {
|
||||
case 'sqlite':
|
||||
return createSQLiteConn(kwargs);
|
||||
break;
|
||||
case 'postgres':
|
||||
return createPostgreSQLConn(kwargs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue