Added & configured typeorm for storing settings
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,3 +10,4 @@ node_modules
|
||||
.output
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
/config/*.sqlite
|
||||
0
config/.gitkeep
Normal file
0
config/.gitkeep
Normal file
1411
package-lock.json
generated
1411
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -53,6 +53,9 @@
|
||||
"hls.js": "^1.4.6",
|
||||
"openapi-fetch": "^0.2.1",
|
||||
"radix-icons-svelte": "^1.2.1",
|
||||
"tailwind-scrollbar-hide": "^1.1.7"
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"sqlite3": "^5.1.6",
|
||||
"tailwind-scrollbar-hide": "^1.1.7",
|
||||
"typeorm": "^0.3.17"
|
||||
}
|
||||
}
|
||||
|
||||
4
src/hooks.server.ts
Normal file
4
src/hooks.server.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import TypeOrm from '$lib/db';
|
||||
import 'reflect-metadata';
|
||||
|
||||
await TypeOrm.getDb();
|
||||
@@ -52,13 +52,15 @@
|
||||
trailerVisible = false;
|
||||
UIVisible = true;
|
||||
|
||||
timeout = setTimeout(() => {
|
||||
trailerMounted = true;
|
||||
|
||||
if ($settings.autoplayTrailers) {
|
||||
timeout = setTimeout(() => {
|
||||
trailerVisible = true;
|
||||
}, TRAILER_LOAD_TIME);
|
||||
}, TRAILER_TIMEOUT - TRAILER_LOAD_TIME);
|
||||
trailerMounted = true; // Mount the trailer
|
||||
|
||||
timeout = setTimeout(() => {
|
||||
trailerVisible = true;
|
||||
}, TRAILER_LOAD_TIME);
|
||||
}, TRAILER_TIMEOUT - TRAILER_LOAD_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
|
||||
35
src/lib/db.ts
Normal file
35
src/lib/db.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import 'reflect-metadata';
|
||||
import { DataSource } from 'typeorm';
|
||||
import { Settings } from './entities/Settings';
|
||||
|
||||
class TypeOrm {
|
||||
private static instance: Promise<DataSource | null> | null = null;
|
||||
|
||||
private constructor() {
|
||||
// Private constructor to prevent external instantiation
|
||||
}
|
||||
|
||||
public static getDb(): Promise<DataSource | null> {
|
||||
if (!TypeOrm.instance) {
|
||||
TypeOrm.instance = new DataSource({
|
||||
type: 'sqlite',
|
||||
database: 'config/reiverr.sqlite',
|
||||
synchronize: true,
|
||||
entities: [Settings],
|
||||
logging: true
|
||||
})
|
||||
.initialize()
|
||||
.then((fulfilled) => {
|
||||
console.info('Data Source has been initialized!');
|
||||
return fulfilled;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Error during Data Source initialization', err);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
return TypeOrm.instance;
|
||||
}
|
||||
}
|
||||
|
||||
export default TypeOrm;
|
||||
78
src/lib/entities/Settings.ts
Normal file
78
src/lib/entities/Settings.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { BaseEntity, Column, Entity, PrimaryColumn } from 'typeorm';
|
||||
|
||||
@Entity({ name: 'settings' })
|
||||
export class Settings extends BaseEntity {
|
||||
@PrimaryColumn('text')
|
||||
name: string;
|
||||
|
||||
@Column('boolean', { default: false })
|
||||
isSetupDone: boolean;
|
||||
|
||||
// General
|
||||
|
||||
@Column('boolean', { default: true })
|
||||
autoplayTrailers: boolean;
|
||||
|
||||
@Column('boolean', { default: true })
|
||||
excludeLibraryItemsFromDiscovery: boolean;
|
||||
|
||||
@Column('text', { default: 'en' })
|
||||
language: string;
|
||||
|
||||
@Column('text', { default: 'US' })
|
||||
region: string;
|
||||
@Column('integer', { default: 150 })
|
||||
animationDuration: number;
|
||||
|
||||
// Discover
|
||||
// @Column()
|
||||
// discoverIncludedLanguages: string[];
|
||||
|
||||
@Column('boolean', { default: true })
|
||||
discoverFilterBasedOnLanguage: boolean;
|
||||
|
||||
// Sonarr
|
||||
|
||||
@Column('integer', { default: 0 })
|
||||
sonarrQualityProfileId: number;
|
||||
|
||||
@Column('integer', { default: 0 })
|
||||
sonarrLanguageProfileId: number;
|
||||
|
||||
@Column('text', { default: '/tv' })
|
||||
sonarrRootFolderPath: string;
|
||||
|
||||
// Radarr
|
||||
|
||||
@Column('integer', { default: 0 })
|
||||
radarrQualityProfileId: number;
|
||||
|
||||
@Column('integer', { default: 0 })
|
||||
radarrProfileId: number;
|
||||
|
||||
@Column('text', { default: '/movies' })
|
||||
radarrRootFolderPath: string;
|
||||
|
||||
// Jellyfin
|
||||
|
||||
@Column('text', { default: '' })
|
||||
jellyfinUserId: string;
|
||||
|
||||
// Playback
|
||||
|
||||
@Column('text', { default: 'reiverr' })
|
||||
preferredPlaybackSource: 'reiverr' | 'jellyfin';
|
||||
|
||||
public static async get(name = 'default'): Promise<Settings> {
|
||||
const settings = await this.findOne({ where: { name } });
|
||||
|
||||
if (!settings) {
|
||||
const defaultSettings = new Settings();
|
||||
defaultSettings.name = 'default';
|
||||
await defaultSettings.save();
|
||||
return defaultSettings;
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
import { get, writable } from 'svelte/store';
|
||||
|
||||
interface Settings {
|
||||
export interface SettingsValues {
|
||||
autoplayTrailers: boolean;
|
||||
excludeLibraryItemsFromDiscovery: boolean;
|
||||
language: string;
|
||||
region: string;
|
||||
animationDuration: number;
|
||||
discover: {
|
||||
includedLanguages: string[];
|
||||
filterBasedOnLanguage: boolean;
|
||||
};
|
||||
animationDuration: number;
|
||||
sonarr: {
|
||||
qualityProfileId: number;
|
||||
rootFolderPath: string;
|
||||
@@ -28,16 +28,16 @@ interface Settings {
|
||||
};
|
||||
}
|
||||
|
||||
const defaultSettings: Settings = {
|
||||
export const defaultSettings: SettingsValues = {
|
||||
autoplayTrailers: true,
|
||||
excludeLibraryItemsFromDiscovery: true,
|
||||
language: 'en',
|
||||
region: 'US',
|
||||
animationDuration: 150,
|
||||
discover: {
|
||||
filterBasedOnLanguage: true,
|
||||
includedLanguages: ['en']
|
||||
},
|
||||
animationDuration: 150,
|
||||
sonarr: {
|
||||
qualityProfileId: 4,
|
||||
rootFolderPath: '/tv',
|
||||
@@ -56,7 +56,7 @@ const defaultSettings: Settings = {
|
||||
}
|
||||
};
|
||||
|
||||
export const settings = writable<Settings>(defaultSettings);
|
||||
export const settings = writable<SettingsValues>();
|
||||
|
||||
export const getIncludedLanguagesQuery = () => {
|
||||
const settingsValue = get(settings);
|
||||
|
||||
44
src/routes/+layout.server.ts
Normal file
44
src/routes/+layout.server.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import {
|
||||
JELLYFIN_API_KEY,
|
||||
JELLYFIN_BASE_URL,
|
||||
RADARR_API_KEY,
|
||||
RADARR_BASE_URL,
|
||||
SONARR_API_KEY,
|
||||
SONARR_BASE_URL
|
||||
} from '$lib/constants';
|
||||
import { Settings } from '$lib/entities/Settings';
|
||||
import type { LayoutServerLoad } from './$types';
|
||||
|
||||
export type MissingEnvironmentVariables = {
|
||||
PUBLIC_RADARR_API_KEY: boolean;
|
||||
PUBLIC_RADARR_BASE_URL: boolean;
|
||||
PUBLIC_SONARR_API_KEY: boolean;
|
||||
PUBLIC_SONARR_BASE_URL: boolean;
|
||||
PUBLIC_JELLYFIN_API_KEY: boolean;
|
||||
PUBLIC_JELLYFIN_URL: boolean;
|
||||
};
|
||||
|
||||
export const load: LayoutServerLoad = async () => {
|
||||
const settings = await Settings.get();
|
||||
|
||||
const isApplicationSetUp =
|
||||
!!RADARR_API_KEY &&
|
||||
!!RADARR_BASE_URL &&
|
||||
!!SONARR_API_KEY &&
|
||||
!!SONARR_BASE_URL &&
|
||||
!!JELLYFIN_API_KEY &&
|
||||
!!JELLYFIN_BASE_URL;
|
||||
|
||||
return {
|
||||
settings: JSON.parse(JSON.stringify(settings)),
|
||||
isApplicationSetUp,
|
||||
missingEnvironmentVariables: {
|
||||
PUBLIC_RADARR_API_KEY: !RADARR_API_KEY,
|
||||
PUBLIC_RADARR_BASE_URL: !RADARR_BASE_URL,
|
||||
PUBLIC_SONARR_API_KEY: !SONARR_API_KEY,
|
||||
PUBLIC_SONARR_BASE_URL: !SONARR_BASE_URL,
|
||||
PUBLIC_JELLYFIN_API_KEY: !JELLYFIN_API_KEY,
|
||||
PUBLIC_JELLYFIN_URL: !JELLYFIN_BASE_URL
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -1,12 +1,3 @@
|
||||
import {
|
||||
JELLYFIN_API_KEY,
|
||||
JELLYFIN_BASE_URL,
|
||||
RADARR_API_KEY,
|
||||
RADARR_BASE_URL,
|
||||
SONARR_API_KEY,
|
||||
SONARR_BASE_URL
|
||||
} from '$lib/constants';
|
||||
import type { LayoutLoad } from './$types';
|
||||
// import { dev } from '$app/environment';
|
||||
|
||||
// Disable SSR when running the dev server
|
||||
@@ -14,34 +5,3 @@ import type { LayoutLoad } from './$types';
|
||||
// https://github.com/vitejs/vite/issues/11468
|
||||
// export const ssr = !dev;
|
||||
export const ssr = false;
|
||||
|
||||
export type MissingEnvironmentVariables = {
|
||||
PUBLIC_RADARR_API_KEY: boolean;
|
||||
PUBLIC_RADARR_BASE_URL: boolean;
|
||||
PUBLIC_SONARR_API_KEY: boolean;
|
||||
PUBLIC_SONARR_BASE_URL: boolean;
|
||||
PUBLIC_JELLYFIN_API_KEY: boolean;
|
||||
PUBLIC_JELLYFIN_URL: boolean;
|
||||
};
|
||||
|
||||
export const load = (async () => {
|
||||
const isApplicationSetUp =
|
||||
!!RADARR_API_KEY &&
|
||||
!!RADARR_BASE_URL &&
|
||||
!!SONARR_API_KEY &&
|
||||
!!SONARR_BASE_URL &&
|
||||
!!JELLYFIN_API_KEY &&
|
||||
!!JELLYFIN_BASE_URL;
|
||||
|
||||
return {
|
||||
isApplicationSetUp,
|
||||
missingEnvironmentVariables: {
|
||||
PUBLIC_RADARR_API_KEY: !RADARR_API_KEY,
|
||||
PUBLIC_RADARR_BASE_URL: !RADARR_BASE_URL,
|
||||
PUBLIC_SONARR_API_KEY: !SONARR_API_KEY,
|
||||
PUBLIC_SONARR_BASE_URL: !SONARR_BASE_URL,
|
||||
PUBLIC_JELLYFIN_API_KEY: !JELLYFIN_API_KEY,
|
||||
PUBLIC_JELLYFIN_URL: !JELLYFIN_BASE_URL
|
||||
}
|
||||
};
|
||||
}) satisfies LayoutLoad;
|
||||
|
||||
@@ -5,7 +5,17 @@
|
||||
import Poster from '$lib/components/Poster/Poster.svelte';
|
||||
import TitleShowcase from '$lib/components/TitleShowcase/TitleShowcase.svelte';
|
||||
import { library } from '$lib/stores/library.store';
|
||||
import { defaultSettings, settings } from '$lib/stores/settings.store';
|
||||
import type { ComponentProps } from 'svelte';
|
||||
import type { LayoutServerData } from './$types';
|
||||
|
||||
export let data: LayoutServerData;
|
||||
const settingsData = data.settings;
|
||||
|
||||
settings.set({
|
||||
...defaultSettings,
|
||||
autoplayTrailers: settingsData.autoplayTrailers
|
||||
});
|
||||
|
||||
let continueWatchingVisible = true;
|
||||
|
||||
|
||||
6
src/routes/api/settings/+server.ts
Normal file
6
src/routes/api/settings/+server.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { Settings } from '$lib/entities/Settings';
|
||||
import { json, type RequestHandler } from '@sveltejs/kit';
|
||||
|
||||
export const GET: RequestHandler = async ({ url }) => {
|
||||
return json(await Settings.get());
|
||||
};
|
||||
@@ -11,6 +11,10 @@
|
||||
"strict": true,
|
||||
"target": "ES2022",
|
||||
"module": "ES2022",
|
||||
"lib": ["es6"],
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"strictPropertyInitialization": false
|
||||
}
|
||||
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
|
||||
//
|
||||
|
||||
@@ -9,5 +9,8 @@ export default defineConfig({
|
||||
// },
|
||||
test: {
|
||||
include: ['src/**/*.{test,spec}.{js,ts}']
|
||||
},
|
||||
ssr: {
|
||||
external: ['reflect-metadata']
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user