feat: use userData electron path for database (subfolder with version)
This has the side effect of no more ormconfig.yml file, and the database connections are now only loaded on demand (as well as running the migrations). BREAKING CHANGE: there is no migration for the old database
This commit is contained in:
parent
41fc16c1c8
commit
e02e0d97e0
|
@ -15,10 +15,9 @@ node_modules
|
||||||
|
|
||||||
# created by testing
|
# created by testing
|
||||||
/store-backup
|
/store-backup
|
||||||
/database-backup
|
/test-paths
|
||||||
|
|
||||||
# managed by application
|
# managed by application
|
||||||
/database
|
|
||||||
/store
|
/store
|
||||||
|
|
||||||
# built app
|
# built app
|
||||||
|
|
|
@ -3,13 +3,12 @@ const ignoreList = [
|
||||||
/^\/\.vscode($|\/)/,
|
/^\/\.vscode($|\/)/,
|
||||||
|
|
||||||
/^\/\.nyc_output($|\/)/,
|
/^\/\.nyc_output($|\/)/,
|
||||||
/^\/database($|\/)/,
|
|
||||||
/^\/database-backup($|\/)/,
|
|
||||||
/^\/declarations($|\/)/,
|
/^\/declarations($|\/)/,
|
||||||
/^\/mocks($|\/)/,
|
/^\/mocks($|\/)/,
|
||||||
/^\/store($|\/)/,
|
/^\/store($|\/)/,
|
||||||
/^\/store-backup($|\/)/,
|
/^\/store-backup($|\/)/,
|
||||||
/^\/templates($|\/)/,
|
/^\/templates($|\/)/,
|
||||||
|
/^\/test-paths($|\/)/,
|
||||||
/^\/tests($|\/)/,
|
/^\/tests($|\/)/,
|
||||||
/^\/workspace($|\/)/,
|
/^\/workspace($|\/)/,
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,24 @@
|
||||||
import { rewiremock } from './rewiremock';
|
|
||||||
import WebContents = Electron.WebContents;
|
import WebContents = Electron.WebContents;
|
||||||
|
import path from 'path';
|
||||||
|
import { rewiremock } from './rewiremock';
|
||||||
|
|
||||||
const electronMock: DeepPartial<typeof Electron> = {
|
const electronMock: DeepPartial<typeof Electron> = {
|
||||||
app: {
|
app: {
|
||||||
on() {},
|
on(): void {},
|
||||||
|
getPath(name: string): string {
|
||||||
|
return path.resolve('test-paths', name);
|
||||||
|
},
|
||||||
|
quit(): void {},
|
||||||
},
|
},
|
||||||
BrowserWindow: class {
|
BrowserWindow: class {
|
||||||
public webContents: DeepPartial<WebContents> = {
|
public webContents: DeepPartial<WebContents> = {
|
||||||
openDevTools() {},
|
openDevTools(): void {},
|
||||||
};
|
};
|
||||||
public loadFile() {}
|
public loadFile(): void {}
|
||||||
public on() {}
|
public on(): void {}
|
||||||
},
|
},
|
||||||
ipcMain: {
|
ipcMain: {
|
||||||
on() {},
|
on(): void {},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"extends": ["../tslint.json"],
|
|
||||||
"rules": {
|
|
||||||
"typedef": false
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
library:
|
|
||||||
type: sqlite
|
|
||||||
database: ./database/library.db
|
|
||||||
entities:
|
|
||||||
- ./src/main/entities/library/*.js
|
|
||||||
migrations:
|
|
||||||
- ./src/main/migrations/library/*.js
|
|
||||||
cli:
|
|
||||||
migrationsDir: ./src/main/migrations/library
|
|
|
@ -11,7 +11,7 @@
|
||||||
"main": "src/main.js",
|
"main": "src/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"postinstall": "npm run rebuild",
|
"postinstall": "npm run rebuild",
|
||||||
"start": "electron . --enable-logging",
|
"start": "electron . --enable-logging --dev",
|
||||||
"rebuild": "electron-rebuild -f -b -t prod,dev,optional",
|
"rebuild": "electron-rebuild -f -b -t prod,dev,optional",
|
||||||
"typeorm:migrate": "npm run typeorm:migrate:library",
|
"typeorm:migrate": "npm run typeorm:migrate:library",
|
||||||
"typeorm:migrate:library": "typeorm migration:run -c library",
|
"typeorm:migrate:library": "typeorm migration:run -c library",
|
||||||
|
@ -41,7 +41,6 @@
|
||||||
"prettier": "prettier --ignore-path .gitignore -c **/*.{html,handlebars,json,{c,sc,sa,le}ss,yml,svelte,md,ts,js}",
|
"prettier": "prettier --ignore-path .gitignore -c **/*.{html,handlebars,json,{c,sc,sa,le}ss,yml,svelte,md,ts,js}",
|
||||||
"prettier:fix": "prettier --ignore-path .gitignore --write **/*.{html,handlebars,json,{c,sc,sa,le}ss,yml,svelte,md,ts,js}",
|
"prettier:fix": "prettier --ignore-path .gitignore --write **/*.{html,handlebars,json,{c,sc,sa,le}ss,yml,svelte,md,ts,js}",
|
||||||
"fix": "npm run lint:check && npm run lint:fix && npm run prettier:fix",
|
"fix": "npm run lint:check && npm run lint:fix && npm run prettier:fix",
|
||||||
"forge:start": "electron-forge start",
|
|
||||||
"forge:make": "electron-forge --platform win32 --arch x64 make",
|
"forge:make": "electron-forge --platform win32 --arch x64 make",
|
||||||
"forge": "npm run build && npm run forge:make",
|
"forge": "npm run build && npm run forge:make",
|
||||||
"precommit": "npm run build && npm run prettier && npm run lint:check && npm run lint && npm run coverage:fast",
|
"precommit": "npm run build && npm run prettier && npm run lint:check && npm run lint && npm run coverage:fast",
|
||||||
|
@ -50,6 +49,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
"jsdom": "^15.2.1",
|
"jsdom": "^15.2.1",
|
||||||
|
"minimist": "^1.2.0",
|
||||||
"node-fetch": "^2.6.0",
|
"node-fetch": "^2.6.0",
|
||||||
"sqlite3": "^4.1.1",
|
"sqlite3": "^4.1.1",
|
||||||
"typeorm": "^0.2.21",
|
"typeorm": "^0.2.21",
|
||||||
|
@ -79,7 +79,6 @@
|
||||||
"handlebars": "^4.5.3",
|
"handlebars": "^4.5.3",
|
||||||
"husky": "^3.1.0",
|
"husky": "^3.1.0",
|
||||||
"lodash": "^4.17.15",
|
"lodash": "^4.17.15",
|
||||||
"minimist": "^1.2.0",
|
|
||||||
"mocha": "^6.2.2",
|
"mocha": "^6.2.2",
|
||||||
"nock": "^11.7.0",
|
"nock": "^11.7.0",
|
||||||
"nyc": "^14.1.1",
|
"nyc": "^14.1.1",
|
||||||
|
|
16
src/main.ts
16
src/main.ts
|
@ -1,13 +1,19 @@
|
||||||
import { app, BrowserWindow } from 'electron';
|
import { app, BrowserWindow } from 'electron';
|
||||||
import os from 'os';
|
|
||||||
|
|
||||||
import './main/controllers/api';
|
|
||||||
import './main/services/database';
|
|
||||||
import * as session from './main/services/session';
|
|
||||||
import BrowserWindowConstructorOptions = Electron.BrowserWindowConstructorOptions;
|
import BrowserWindowConstructorOptions = Electron.BrowserWindowConstructorOptions;
|
||||||
|
import minimist from 'minimist';
|
||||||
|
import os from 'os';
|
||||||
|
import path from 'path';
|
||||||
|
import packageJson from '../package.json';
|
||||||
|
import './main/controllers/api';
|
||||||
|
import * as session from './main/services/session';
|
||||||
|
|
||||||
export let mainWindow: Electron.BrowserWindow;
|
export let mainWindow: Electron.BrowserWindow;
|
||||||
|
|
||||||
|
export let appPath = path.resolve(
|
||||||
|
app.getPath('userData'),
|
||||||
|
`${packageJson.version}${minimist(process.argv).dev ? '-dev' : ''}`
|
||||||
|
);
|
||||||
|
|
||||||
async function createWindow(): Promise<void> {
|
async function createWindow(): Promise<void> {
|
||||||
session.setHeaders();
|
session.setHeaders();
|
||||||
|
|
||||||
|
|
|
@ -1,30 +1,50 @@
|
||||||
|
import path from 'path';
|
||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
import { Connection, createConnection } from 'typeorm';
|
import { Connection, createConnection as ormCreateConnection } from 'typeorm';
|
||||||
import { throwError } from './error';
|
import { SqliteConnectionOptions } from 'typeorm/driver/sqlite/SqliteConnectionOptions';
|
||||||
|
import { appPath } from '../../main';
|
||||||
|
|
||||||
export enum Databases {
|
export enum Databases {
|
||||||
LIBRARY = 'library',
|
LIBRARY = 'library',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MyConnectionOptions = { [key in Databases]?: SqliteConnectionOptions };
|
||||||
|
|
||||||
|
const databasePath = path.resolve(appPath, 'database');
|
||||||
|
const connectionOptions: MyConnectionOptions = Object.values(Databases).reduce(
|
||||||
|
(prev: MyConnectionOptions, database: Databases) => {
|
||||||
|
prev[database] = {
|
||||||
|
type: 'sqlite',
|
||||||
|
database: path.resolve(databasePath, `${database}.db`),
|
||||||
|
entities: [`./src/main/entities/${database}/*.js`],
|
||||||
|
migrations: [`./src/main/migrations/${database}/*.js`],
|
||||||
|
cli: {
|
||||||
|
migrationsDir: `./src/main/migrations/${database}`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return prev;
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
const connections: {
|
const connections: {
|
||||||
[key in Databases]?: Connection;
|
[key in Databases]?: Connection;
|
||||||
} = {};
|
} = {};
|
||||||
|
|
||||||
Object.values(Databases).forEach((database: Databases) => {
|
function createConnection(database: Databases): Promise<Connection> {
|
||||||
createConnection(database)
|
return ormCreateConnection(connectionOptions[database])
|
||||||
.then((connection: Connection) => {
|
.then((connection: Connection) => {
|
||||||
connections[database] = connection;
|
connections[database] = connection;
|
||||||
return connection.runMigrations();
|
return connection.runMigrations();
|
||||||
})
|
})
|
||||||
.catch((reason: any) => {
|
.then(() => {
|
||||||
throwError(reason, true);
|
return connections[database];
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
export function getConnection(database: Databases): Promise<Connection> {
|
export function getConnection(database: Databases): Promise<Connection> {
|
||||||
if (connections[database] === undefined) {
|
if (connections[database] === undefined) {
|
||||||
return createConnection(database).then((connection: Connection) => {
|
return createConnection(database).then((connection: Connection) => {
|
||||||
connections[database] = connection;
|
|
||||||
return connection;
|
return connection;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import rewiremock from 'rewiremock';
|
||||||
|
import '../../../mocks/electron';
|
||||||
|
|
||||||
|
import { expect } from 'chai';
|
||||||
|
import 'mocha';
|
||||||
|
import { Databases, getConnection } from '../../../src/main/services/database';
|
||||||
|
|
||||||
|
describe('Database Service', () => {
|
||||||
|
before(() => {
|
||||||
|
rewiremock.enable();
|
||||||
|
});
|
||||||
|
|
||||||
|
after(() => {
|
||||||
|
rewiremock.disable();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns a connection', async () => {
|
||||||
|
const libraryConnection = await getConnection(Databases.LIBRARY);
|
||||||
|
expect(libraryConnection).to.not.equal(undefined);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue