automatic service registration à la Svelte
This commit is contained in:
@@ -2,16 +2,24 @@ title: 'Hello World !!'
|
|||||||
subtitle: 'actually, I am a new pilot.'
|
subtitle: 'actually, I am a new pilot.'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
cloud:
|
cloud:
|
||||||
title: '/Cloud'
|
title: '/Cloud'
|
||||||
subtitle: 'Private Cloud Utilities'
|
subtitle: 'Private Cloud Utilities'
|
||||||
icon: 'fas fa-cloud'
|
icon: 'fas fa-cloud'
|
||||||
items:
|
items:
|
||||||
nas:
|
nas:
|
||||||
title: 'NAS'
|
title: 'NAS'
|
||||||
subtitle: 'Network Attached Storage'
|
subtitle: 'Network Attached Storage'
|
||||||
icon: 'fas fa-hard-drive'
|
icon: 'fas fa-hard-drive'
|
||||||
target: '_blank'
|
target: '_blank'
|
||||||
url: '/NAS'
|
url: '/NAS'
|
||||||
type: 'hello'
|
keywords: 'cloud storage files'
|
||||||
keywords: 'cloud storage files'
|
type: prowlarr
|
||||||
|
pihole:
|
||||||
|
title: 'PiHole'
|
||||||
|
subtitle: 'A DNS Hole'
|
||||||
|
icon: 'fas fa-hard-drive'
|
||||||
|
target: '_blank'
|
||||||
|
url: '/pihole'
|
||||||
|
type: 'pihole'
|
||||||
|
keywords: 'cloud storage files'
|
||||||
|
|||||||
3
src/hooks.server.ts
Normal file
3
src/hooks.server.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { initServices } from '$lib/services/services';
|
||||||
|
|
||||||
|
await initServices();
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import type { ServiceConfig } from '$lib/config';
|
|
||||||
|
|
||||||
export let data: ServiceConfig;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="service-card">
|
|
||||||
<title>{data.title}</title>
|
|
||||||
</div>
|
|
||||||
9
src/lib/services/pihole/+service.ts
Normal file
9
src/lib/services/pihole/+service.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { type ServiceHandler } from '../service';
|
||||||
|
|
||||||
|
export const handle: ServiceHandler = ({ config }) => {
|
||||||
|
const data = {};
|
||||||
|
if (config.apikey != undefined) {
|
||||||
|
//TODO: fetch data
|
||||||
|
}
|
||||||
|
return { data, componentPath: 'pihole/PiHoleContent.svelte' };
|
||||||
|
};
|
||||||
5
src/lib/services/pihole/PiHoleContent.svelte
Normal file
5
src/lib/services/pihole/PiHoleContent.svelte
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export const data = undefined;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<p>pihole status</p>
|
||||||
5
src/lib/services/prowlarr/+service.ts
Normal file
5
src/lib/services/prowlarr/+service.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import type { ServiceHandler } from '../service';
|
||||||
|
|
||||||
|
export const handle: ServiceHandler = () => {
|
||||||
|
return { data: {}, componentPath: 'prowlarr/ProwlarrContent.svelte' };
|
||||||
|
};
|
||||||
5
src/lib/services/prowlarr/ProwlarrContent.svelte
Normal file
5
src/lib/services/prowlarr/ProwlarrContent.svelte
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export const data = undefined;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<p>Prowlarr content</p>
|
||||||
@@ -5,26 +5,7 @@ interface ServiceHandlerArgs {
|
|||||||
config: ServiceConfig;
|
config: ServiceConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ServiceHandler = (input: Partial<ServiceHandlerArgs>) => {
|
export type ServiceHandler = (input: ServiceHandlerArgs) => {
|
||||||
data: Record<string, unknown>;
|
data: Record<string, unknown>;
|
||||||
componentPath: string;
|
componentPath: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const services: Record<string, [ServiceHandler, string]> = {};
|
|
||||||
|
|
||||||
export function registerService(type: string, handler: ServiceHandler) {
|
|
||||||
services[type] = [handler, type];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getService(type: string): [ServiceHandler, string] {
|
|
||||||
const handler = services[type];
|
|
||||||
if (handler == undefined) {
|
|
||||||
return [
|
|
||||||
() => {
|
|
||||||
return { data: {}, componentPath: 'generic/GenericServiceCard.svelte' };
|
|
||||||
},
|
|
||||||
'generic'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|||||||
33
src/lib/services/services.ts
Normal file
33
src/lib/services/services.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import type { ServiceHandler } from './service';
|
||||||
|
|
||||||
|
const services: Record<string, [ServiceHandler, string]> = {};
|
||||||
|
|
||||||
|
function registerService(type: string, handler: ServiceHandler) {
|
||||||
|
services[type] = [handler, type];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getService(type: string): [ServiceHandler, string] {
|
||||||
|
const handler = services[type];
|
||||||
|
if (handler == undefined) {
|
||||||
|
return [
|
||||||
|
() => {
|
||||||
|
return { data: {}, componentPath: '' };
|
||||||
|
},
|
||||||
|
''
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function initServices() {
|
||||||
|
const services = import.meta.glob('/src/lib/services/**/+service.ts');
|
||||||
|
|
||||||
|
for (const [path, load] of Object.entries(services)) {
|
||||||
|
const { handle } = (await load()) as any;
|
||||||
|
if (handle == undefined) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const typeName = path.slice(18, -12);
|
||||||
|
registerService(typeName, handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ import { config, stripPrivateFields, type Config, type ServiceConfig } from '$li
|
|||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
import * as yml from 'js-yaml';
|
import * as yml from 'js-yaml';
|
||||||
import { readFile } from 'fs/promises';
|
import { readFile } from 'fs/promises';
|
||||||
import { getService } from '$lib/services/service';
|
import { getService } from '$lib/services/services';
|
||||||
|
|
||||||
async function reloadConfig(): Promise<Config> {
|
async function reloadConfig(): Promise<Config> {
|
||||||
if (dev) {
|
if (dev) {
|
||||||
@@ -34,6 +34,7 @@ export const load: PageServerLoad = async ({ fetch, depends }) => {
|
|||||||
const clientService = clientGroup.items[service] as ServiceConfig;
|
const clientService = clientGroup.items[service] as ServiceConfig;
|
||||||
|
|
||||||
const [handler, type] = getService(serverService.type || '');
|
const [handler, type] = getService(serverService.type || '');
|
||||||
|
|
||||||
clientService.type = type;
|
clientService.type = type;
|
||||||
Object.assign(clientService, handler({ fetch, config: serverService }));
|
Object.assign(clientService, handler({ fetch, config: serverService }));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,18 +12,23 @@ export const load: PageLoad = async ({ data }) => {
|
|||||||
);
|
);
|
||||||
for (const s of services) {
|
for (const s of services) {
|
||||||
const service = data.config.services[group].items[s];
|
const service = data.config.services[group].items[s];
|
||||||
|
if (service.componentPath == '' || service.type == '') {
|
||||||
if (components[service.type || 'generic'] != undefined) {
|
delete service.componentPath;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const path =
|
const componentType = service.type || '';
|
||||||
'../lib/services/' + (service.componentPath || 'generic/GenericServiceCard.svelte');
|
if (components[componentType] != undefined) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const path = '../lib/services/' + service.componentPath;
|
||||||
|
|
||||||
const module = await import(/* @vite-ignore */ path);
|
const module = await import(/* @vite-ignore */ path);
|
||||||
|
|
||||||
components[service.type || 'generic'] = module.default;
|
components[componentType] = module.default;
|
||||||
|
|
||||||
delete service.componentPath;
|
//service.componentPath = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user