Switches to a global variable for client/serverConfig

This commit is contained in:
2023-08-14 12:37:45 +02:00
parent c531e7231d
commit eb32347990
4 changed files with 73 additions and 36 deletions

View File

@@ -23,9 +23,7 @@ export interface ServiceGroupConfig extends SectionConfig {
[x: string]: unknown; [x: string]: unknown;
} }
export interface ColorConfig { export type ColorConfig = Record<string, string>;
test: string;
}
export interface Config extends SectionConfig { export interface Config extends SectionConfig {
services: Array<ServiceGroupConfig>; services: Array<ServiceGroupConfig>;

View File

@@ -4,17 +4,15 @@ import type { Config } from '$lib/config';
describe('Config', () => { describe('Config', () => {
it('should be export a build time server and client config store', () => { it('should be export a build time server and client config store', () => {
expect(serverConfig).toBeTruthy(); expect(serverConfig()).toBeTruthy();
expect(clientConfig).toBeTruthy(); expect(clientConfig()).toBeTruthy();
}); });
it('should be able to merge with POJO', () => { it('should be able to merge with POJO', () => {
const merged: Config = merge<Config>(defaultConfig, { const merged: Config = merge<Config>(defaultConfig, {
subtitle: "Homer's favorite neighboor", subtitle: "Homer's favorite neighboor",
colors: { colors: {
light: { light: { notInDefault: 'foo' }
test: 'red'
}
}, },
services: [ services: [
{ {
@@ -27,12 +25,16 @@ describe('Config', () => {
] ]
} }
] ]
}) as Config; });
expect(merged.title).toEqual('Flanders'); expect(merged.title).toEqual('Flanders');
expect(merged.services).toHaveLength(1); expect(merged.services).toHaveLength(1);
expect(merged.colors.light).toEqual({ test: 'red' }); expect(Object.entries(merged.colors.light)).toHaveLength(
expect(merged.colors.dark).toEqual({}); Object.entries(merged.colors.dark).length + 1
);
expect(Object.entries(defaultConfig.colors.light)).toHaveLength(
Object.entries(merged.colors.light).length - 1
);
expect(merged.services[0].title).toEqual('favorite occupations'); expect(merged.services[0].title).toEqual('favorite occupations');
expect(merged.services[0].items).toHaveLength(1); expect(merged.services[0].items).toHaveLength(1);
expect(merged.services[0].items[0].title).toEqual('anoy homer'); expect(merged.services[0].items[0].title).toEqual('anoy homer');
@@ -44,7 +46,9 @@ describe('Config', () => {
title: 'custom', title: 'custom',
secret: { secret: 'some secret' }, secret: { secret: 'some secret' },
colors: { colors: {
light: {}, light: {
test: 'foo'
},
dark: {} dark: {}
}, },
services: [ services: [
@@ -66,6 +70,8 @@ describe('Config', () => {
const stripped: Config = stripPrivateFields(custom); const stripped: Config = stripPrivateFields(custom);
expect(stripped.secret).toBeUndefined(); expect(stripped.secret).toBeUndefined();
expect(stripped.colors.light).toEqual({ test: 'foo' });
expect(stripped.colors.dark).toEqual({});
expect(custom.secret).toEqual({ secret: 'some secret' }); expect(custom.secret).toEqual({ secret: 'some secret' });
expect(stripped.services[0].secret).toBeUndefined(); expect(stripped.services[0].secret).toBeUndefined();
expect(custom.services[0].secret).toEqual('secret'); expect(custom.services[0].secret).toEqual('secret');

View File

@@ -1,8 +1,7 @@
import { writable, type Readable, type Writable, derived } from 'svelte/store';
import configData from '../../config.yml'; import configData from '../../config.yml';
import { readFile, watch } from 'fs/promises'; import { readFile, watch } from 'fs/promises';
import * as yml from 'js-yaml'; import * as yml from 'js-yaml';
import type { Config, ServiceConfig, ServiceGroupConfig } from '$lib/config'; import type { ColorConfig, Config, ServiceConfig, ServiceGroupConfig } from '$lib/config';
const requiredService: Required<ServiceConfig> = { const requiredService: Required<ServiceConfig> = {
title: '', title: '',
@@ -31,12 +30,8 @@ export const requiredConfig: Required<Config> = {
icon: '', icon: '',
asmask: false, asmask: false,
colors: { colors: {
light: { light: {},
test: '' dark: {}
},
dark: {
test: ''
}
}, },
services: [requiredServiceGroup] services: [requiredServiceGroup]
}; };
@@ -46,7 +41,6 @@ type SPOJO = Record<string, unknown>;
export function merge<Type extends SPOJO>(a: Type, b: SPOJO): Type { export function merge<Type extends SPOJO>(a: Type, b: SPOJO): Type {
const res: Type = { ...a }; const res: Type = { ...a };
for (const [key, value] of Object.entries(b)) { for (const [key, value] of Object.entries(b)) {
console.log(key, value, typeof value, typeof res[key]);
if ( if (
typeof value != 'object' || typeof value != 'object' ||
res[key] == undefined || res[key] == undefined ||
@@ -69,15 +63,41 @@ export function merge<Type extends SPOJO>(a: Type, b: SPOJO): Type {
return res; return res;
} }
const defaultLightConfig: ColorConfig = {};
defaultLightConfig['highlight-primary'] = '#3367d6';
defaultLightConfig['highlight-secondary'] = '#4285f4';
defaultLightConfig['highlight-hover'] = '#5a95f5';
defaultLightConfig['background'] = '#f5f5f5';
defaultLightConfig['card-background'] = '#ffffff';
defaultLightConfig['text'] = '#363636';
defaultLightConfig['text-header'] = '#ffffff';
defaultLightConfig['text-title'] = '#303030';
defaultLightConfig['text-subtitle'] = '#424242';
defaultLightConfig['card-shadow'] = 'rgba(0, 0, 0, 0.1)';
defaultLightConfig['link'] = '#3273dc';
defaultLightConfig['link-hover'] = '#363636';
defaultLightConfig['background-image'] = '';
const defaultDarkConfig: ColorConfig = {};
defaultDarkConfig['highlight-primary'] = '#3367d6';
defaultDarkConfig['highlight-secondary'] = '#4285f4';
defaultDarkConfig['highlight-hover'] = '#5a95f5';
defaultDarkConfig['background'] = '#131313';
defaultDarkConfig['card-background'] = '#2b2b2b';
defaultDarkConfig['text'] = '#eaeaea';
defaultDarkConfig['text-header'] = '#ffffff';
defaultDarkConfig['text-title'] = '#fafafa';
defaultDarkConfig['text-subtitle'] = '#f5f5f5';
defaultDarkConfig['card-shadow'] = 'rgba(0, 0, 0, 0.4)';
defaultDarkConfig['link'] = '#3273dc';
defaultDarkConfig['link-hover'] = '#ffdd57';
defaultDarkConfig['background-image'] = '';
export const defaultConfig: Config = { export const defaultConfig: Config = {
title: 'Flanders', title: 'Flanders',
colors: { colors: {
light: { light: defaultLightConfig,
test: '' dark: defaultDarkConfig
},
dark: {
test: ''
}
}, },
services: [] services: []
@@ -115,14 +135,27 @@ function strip<Type extends SPOJO>(toStrip: Type, reference: Type): Type {
} }
export function stripPrivateFields(config: Config): Config { export function stripPrivateFields(config: Config): Config {
return strip(config, requiredConfig); const res = strip(config, requiredConfig);
if (config?.colors?.dark != undefined) {
res.colors.dark = config.colors.dark;
}
if (config?.colors?.light != undefined) {
res.colors.light = config.colors.light;
}
return res;
} }
export const serverConfig: Writable<Config> = writable(merge<Config>(defaultConfig, configData)); export function serverConfig(): Config {
return _serverConfig;
}
export const clientConfig: Readable<Config> = derived(serverConfig, ($config) => export function clientConfig(): Config {
stripPrivateFields($config) return _clientConfig;
); }
let _serverConfig = merge<Config>(defaultConfig, configData);
let _clientConfig = stripPrivateFields(_serverConfig);
export function watchDymamicConfig() { export function watchDymamicConfig() {
const __filepath = '/dynamic/config.yml'; const __filepath = '/dynamic/config.yml';
@@ -130,7 +163,8 @@ export function watchDymamicConfig() {
const reloadConfig = async () => { const reloadConfig = async () => {
try { try {
const dynamicConfig = yml.load(await readFile(__filepath, 'utf8')); const dynamicConfig = yml.load(await readFile(__filepath, 'utf8'));
serverConfig.set(merge<Config>(defaultConfig, dynamicConfig)); _serverConfig = merge<Config>(defaultConfig, dynamicConfig);
_clientConfig = stripPrivateFields(_serverConfig);
} catch (err) { } catch (err) {
console.error('could not read or parse config: ' + err); console.error('could not read or parse config: ' + err);
} }

View File

@@ -1,13 +1,12 @@
import { clientConfig, serverConfig } from '$lib/server/config'; import { clientConfig, serverConfig } from '$lib/server/config';
import { get } from 'svelte/store';
import type { PageServerLoad } from './$types'; import type { PageServerLoad } from './$types';
import { getServiceHandler } from '$lib/services/services'; import { getServiceHandler } from '$lib/services/services';
export const load: PageServerLoad = ({ fetch }) => { export const load: PageServerLoad = ({ fetch }) => {
const config = get(clientConfig);
const serviceData: Array<Array<unknown>> = []; const serviceData: Array<Array<unknown>> = [];
const config = clientConfig();
for (const [i, group] of get(serverConfig).services.entries()) { for (const [i, group] of serverConfig().services.entries()) {
const groupData: Array<unknown> = []; const groupData: Array<unknown> = [];
serviceData.push(groupData); serviceData.push(groupData);
for (const [j, service] of group.items.entries()) { for (const [j, service] of group.items.entries()) {