From 9903497867379ee622fa97c57ce4c067dcc86ba7 Mon Sep 17 00:00:00 2001 From: Alexandre Tuleu Date: Fri, 11 Aug 2023 17:04:39 +0200 Subject: [PATCH] Makes finally dynamic component work?? --- src/config.yml | 6 ++++-- src/lib/config.test.ts | 18 +++++++++--------- src/lib/config.ts | 34 +++++++++++++--------------------- src/lib/services/service.ts | 15 +++++++++------ src/routes/+page.server.ts | 24 ++++++++++++++---------- src/routes/+page.ts | 24 ++++++++++++++++++++---- 6 files changed, 69 insertions(+), 52 deletions(-) diff --git a/src/config.yml b/src/config.yml index 6613356..9d097dd 100644 --- a/src/config.yml +++ b/src/config.yml @@ -2,11 +2,13 @@ title: 'Hello World !!' subtitle: 'actually, I am a new pilot.' services: - - title: '/Cloud' + cloud: + title: '/Cloud' subtitle: 'Private Cloud Utilities' icon: 'fas fa-cloud' items: - - title: 'NAS' + nas: + title: 'NAS' subtitle: 'Network Attached Storage' icon: 'fas fa-hard-drive' target: '_blank' diff --git a/src/lib/config.test.ts b/src/lib/config.test.ts index b9e4617..5950b69 100644 --- a/src/lib/config.test.ts +++ b/src/lib/config.test.ts @@ -33,26 +33,26 @@ describe('Config', () => { it('should be able to strip custom keys', () => { const custom: Config = { title: 'custom', - secret: {secret: 'some secret'}, - services: [ - { + secret: { secret: 'some secret' }, + services: { + top: { title: 'top services', secret: 'secret', - items: [ - { + items: { + top: { title: 'top service', url: 'somewhere', secret: 'secret' } - ] + } } - ] + } }; const stripped: Config = stripPrivateFields(custom); expect(stripped.secret).toBeUndefined(); - expect(stripped.services[0].secret).toBeUndefined(); - expect(stripped.services[0].items[0].secret).toBeUndefined(); + expect(stripped.services.top.secret).toBeUndefined(); + expect(stripped.services.top.items.top.secret).toBeUndefined(); }); }); diff --git a/src/lib/config.ts b/src/lib/config.ts index fb48132..afcb8b4 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -21,13 +21,13 @@ export interface ServiceConfig extends SectionConfig { } export interface ServiceGroupConfig extends SectionConfig { - items: ServiceConfig[]; + items: Record; [x: string]: unknown; } export interface Config extends SectionConfig { - services: ServiceGroupConfig[]; + services: Record; [x: string]: unknown; } @@ -41,17 +41,17 @@ type DeepRequired = T extends object const requiredConfig: DeepRequired = { title: '', subtitle: '', - services: [ - { + services: { + default: { title: '', - items: [ - { + items: { + default: { title: '', url: '' } - ] + } } - ] + } }; export function mergeConfig(a: Config, b: any): Config { @@ -61,7 +61,7 @@ export function mergeConfig(a: Config, b: any): Config { export const defaultConfig: Config = { title: 'Flanders', - services: [] + services: {} }; type SPOJO = Record; @@ -70,29 +70,21 @@ function strip(toStrip: Type, reference: Type): Type { const res: Type = { ...toStrip }; const referenceNames = Object.entries(reference).map(([key, value]) => key); + const allowAny: boolean = referenceNames.length == 1 && referenceNames[0] == 'default'; for (const [key, value] of Object.entries(res)) { - if (referenceNames.includes(key) == false) { + if (referenceNames.includes(key) == false && allowAny == false) { // remove the object delete res[key]; continue; } - - // strips further arrays - if (value instanceof Array) { - const stripped: SPOJO = {}; - const childRef = (reference[key] as Array)[0]; - stripped[key] = value.map((v: SPOJO) => strip(v, childRef)); - Object.assign(res, stripped); - continue; - } - if (typeof value != 'object') { continue; } // it is a child object, we strip it further const stripped: SPOJO = {}; - stripped[key] = strip(value as SPOJO, reference[key] as SPOJO); + const childReference: SPOJO = reference[allowAny ? 'default' : key] as SPOJO; + stripped[key] = strip(value as SPOJO, childReference); Object.assign(res, stripped); } return res; diff --git a/src/lib/services/service.ts b/src/lib/services/service.ts index a441996..6d09a3b 100644 --- a/src/lib/services/service.ts +++ b/src/lib/services/service.ts @@ -10,18 +10,21 @@ export type ServiceHandler = (input: Partial) => { componentPath: string; }; -const services: Record = {}; +const services: Record = {}; export function registerService(type: string, handler: ServiceHandler) { - services[type] = handler; + services[type] = [handler, type]; } -export function getService(type: string): ServiceHandler { +export function getService(type: string): [ServiceHandler, string] { const handler = services[type]; if (handler == undefined) { - return () => { - return { data: {}, componentPath: 'generic/GenericServiceCard.svelte' }; - }; + return [ + () => { + return { data: {}, componentPath: 'generic/GenericServiceCard.svelte' }; + }, + 'generic' + ]; } return handler; } diff --git a/src/routes/+page.server.ts b/src/routes/+page.server.ts index 3dc175b..00b15f2 100644 --- a/src/routes/+page.server.ts +++ b/src/routes/+page.server.ts @@ -1,5 +1,5 @@ import { dev } from '$app/environment'; -import { config, stripPrivateFields, type Config } from '$lib/config'; +import { config, stripPrivateFields, type Config, type ServiceConfig } from '$lib/config'; import type { PageServerLoad } from './$types'; import * as yml from 'js-yaml'; import { readFile } from 'fs/promises'; @@ -17,23 +17,27 @@ async function reloadConfig(): Promise { } } -function zip(a: Array, b: Array): Array> { - const size = Math.min(a.length, b.length); - return a.slice(0, size).map((v, i) => [v, b[i]]); -} - export const load: PageServerLoad = async ({ fetch, depends }) => { depends('app:state'); const serverConfig = await reloadConfig(); const clientConfig = stripPrivateFields(serverConfig); + const groups: Array = Object.entries(serverConfig.services).map(([k, v]) => k); + for (const group of groups) { + const serverGroup = serverConfig.services[group]; + const clientGroup = clientConfig.services[group]; - for (const [serverGroup, clientGroup] of zip(serverConfig.services, clientConfig.services)) { - for (const [serverService, clientService] of zip(serverGroup.items, clientGroup.items)) { - const handler = getService(serverService.type || ''); + const services = Object.entries(serverGroup.items).map(([k, v]) => k); + + for (const service of services) { + const serverService = serverGroup.items[service] as ServiceConfig; + const clientService = clientGroup.items[service] as ServiceConfig; + + const [handler, type] = getService(serverService.type || ''); + clientService.type = type; Object.assign(clientService, handler({ fetch, config: serverService })); } } clientConfig.timestamp = new Date(); - return { config: clientConfig }; + return { config: clientConfig, cool: true }; }; diff --git a/src/routes/+page.ts b/src/routes/+page.ts index 0385991..7979d63 100644 --- a/src/routes/+page.ts +++ b/src/routes/+page.ts @@ -1,15 +1,31 @@ import type { PageLoad } from './$types'; export const load: PageLoad = async ({ data }) => { - for (const group of data.config.services) { - for (const service of group.items) { + const config = { ...data.config }; + const groups: Array = Object.entries(config.services).map(([k, v]) => k); + + const components: Record = {}; + + for (const group of groups) { + const services: Array = Object.entries(config.services[group].items).map( + ([k, v]) => k + ); + for (const s of services) { + const service = data.config.services[group].items[s]; + + if (components[service.type || 'generic'] != undefined) { + continue; + } + const path = '../lib/services/' + (service.componentPath || 'generic/GenericServiceCard.svelte'); const module = await import(/* @vite-ignore */ path); - service.component = module.default; + components[service.type || 'generic'] = module.default; + delete service.componentPath; } } - return { config: data.config }; + + return { config, components }; };