Added dynamic dataLoader importing and fixing race conditions

This commit is contained in:
Samuel Andert 2023-07-26 18:28:31 +02:00
parent a3761140bd
commit 371e42e4ee
6 changed files with 112 additions and 106 deletions

View File

@ -26,34 +26,44 @@
} }
export let composite: IComposite; export let composite: IComposite;
let loadedServices: Record<string, any> = {}; let loadedServices: Record<string, any> = {};
let layoutStyle = '';
// Reactive loading mechanism for services based on composite changes $: {
$: if (composite?.services) { // Create layout style reactively
composite.services.forEach(async (serviceName) => { layoutStyle = computeLayoutStyle(composite?.layout);
// Load services reactively
if (composite?.services) {
for (const serviceName of composite.services) {
if (!loadedServices[serviceName]) { if (!loadedServices[serviceName]) {
loadedServices[serviceName] = await loadService(serviceName); // Note: We're ignoring async operation here, you might want to handle it if needed
} loadService(serviceName).then((service) => {
loadedServices[serviceName] = service;
}); });
} }
}
}
$: layoutStyle = composite?.layout // Initialize composite state reactively
? ` if (composite?.children) {
grid-template-areas: ${composite.layout.areas};
${composite.layout.gap ? `gap: ${composite.layout.gap};` : ''}
${composite.layout.columns ? `grid-template-columns: ${composite.layout.columns};` : ''}
${composite.layout.rows ? `grid-template-rows: ${composite.layout.rows};` : ''}
`
: '';
// Reactive statement to watch changes in the composite prop
$: if (composite?.children) {
composite.children.forEach((child) => { composite.children.forEach((child) => {
initializeCompositeState(child); initializeCompositeState(child);
mapAndSubscribe(child); mapAndSubscribe(child);
}); });
} }
}
function computeLayoutStyle(layout?: ICompositeLayout) {
if (!layout) return '';
return `
grid-template-areas: ${layout.areas};
${layout.gap ? `gap: ${layout.gap};` : ''}
${layout.columns ? `grid-template-columns: ${layout.columns};` : ''}
${layout.rows ? `grid-template-rows: ${layout.rows};` : ''}
`;
}
function initializeCompositeState(child: IComposite) { function initializeCompositeState(child: IComposite) {
if (child.id) { if (child.id) {
@ -65,6 +75,8 @@
} }
} }
let unsubscribers = [];
function mapAndSubscribe(component: IComposite) { function mapAndSubscribe(component: IComposite) {
console.log('Mapping and subscribing for:', component.id); console.log('Mapping and subscribing for:', component.id);
@ -77,14 +89,13 @@
if (externalID === 'data') { if (externalID === 'data') {
const unsubscribe = dataStore.subscribe((store) => { const unsubscribe = dataStore.subscribe((store) => {
if (externalKey in store) { if (externalKey in store) {
// Check if the data item is a Svelte store
if (store[externalKey] && typeof store[externalKey].subscribe === 'function') { if (store[externalKey] && typeof store[externalKey].subscribe === 'function') {
let innerUnsub = store[externalKey].subscribe((value) => { let innerUnsub = store[externalKey].subscribe((value) => {
localStore.update((storeValue) => { localStore.update((storeValue) => {
return { ...storeValue, [localKey]: value }; return { ...storeValue, [localKey]: value };
}); });
}); });
onDestroy(innerUnsub); unsubscribers.push(innerUnsub);
} else { } else {
localStore.update((storeValue) => { localStore.update((storeValue) => {
return { ...storeValue, [localKey]: store[externalKey] }; return { ...storeValue, [localKey]: store[externalKey] };
@ -93,7 +104,7 @@
} }
}); });
onDestroy(unsubscribe); unsubscribers.push(unsubscribe);
} else { } else {
const externalStore = getCompositeStore(externalID); const externalStore = getCompositeStore(externalID);
if (externalStore) { if (externalStore) {
@ -105,7 +116,7 @@
} }
}); });
onDestroy(unsubscribe); unsubscribers.push(unsubscribe);
} }
} }
} }
@ -116,6 +127,11 @@
} }
} }
// Call all unsubscribe methods when the component is destroyed.
onDestroy(() => {
unsubscribers.forEach((unsub) => unsub());
});
async function getComponent(componentName: string) { async function getComponent(componentName: string) {
if (components[componentName]) { if (components[componentName]) {
const module = await components[componentName](); const module = await components[componentName]();

View File

@ -1,11 +1,30 @@
// dataLoader.ts // dataLoader.ts
import { writable } from 'svelte/store'; import { writable } from 'svelte/store';
import { queryMessagesData } from '$lib/data/queryMessages'; import dataSources from 'virtual:data-sources-list'; // Import the generated list
import { queryTodosData } from '$lib/data/queryTodos';
// The store that holds the data sets // The store that holds the data sets
export const dataStore = writable({ export const dataStore = writable({});
queryMessages: queryMessagesData,
queryTodos: queryTodosData // Dynamically import the data modules and assign them to the store
dataSources.forEach(src => {
import(`/src/lib/data/${src}.ts`).then(module => {
// Here, explicitly extract the required data or function from the module
const moduleData = module[src] || module.default;
dataStore.update(store => ({ ...store, [src]: moduleData }));
});
}); });
// // dataLoader.ts
// import { writable } from 'svelte/store';
// import { queryMessages } from '$lib/data/queryMessages';
// import { queryTodos } from '$lib/data/queryTodos';
// // The store that holds the data sets
// export const dataStore = writable({
// queryMessages: queryMessages,
// queryTodos: queryTodos
// });

View File

@ -35,4 +35,4 @@ messages.subscribe(currentMessages => {
setToLocalStorage('chat-messages', currentMessages); setToLocalStorage('chat-messages', currentMessages);
}); });
export const queryMessagesData = messages; export const queryMessages = messages;

View File

@ -1,7 +1,7 @@
// $lib/data/queryTodos.ts // $lib/data/queryTodos.ts
import { writable } from 'svelte/store'; import { writable } from 'svelte/store';
export const queryTodosData = writable([ export const queryTodos = writable([
{ {
id: "id1", id: "id1",
text: "todo 1" text: "todo 1"

View File

@ -1,6 +1,6 @@
// $lib/services/messages.ts // $lib/services/messages.ts
import { queryMessagesData } from '$lib/data/queryMessages'; import { queryMessages } from '$lib/data/queryMessages';
// The createMessage function now accepts a messageData parameter. // The createMessage function now accepts a messageData parameter.
export function createMessage(messageData) { export function createMessage(messageData) {
@ -15,78 +15,9 @@ export function createMessage(messageData) {
// We use the $ prefix to get the value out of a Svelte store // We use the $ prefix to get the value out of a Svelte store
// and then set the new value back into the store. // and then set the new value back into the store.
queryMessagesData.update(oldMessages => [...oldMessages, newMessageObj]); queryMessages.update(oldMessages => [...oldMessages, newMessageObj]);
} }
export function clearMessages() { export function clearMessages() {
queryMessagesData.set([]); queryMessages.set([]);
} }
// import { writable } from 'svelte/store';
// // Helper function to determine if we're running on the client side (browser) or server side.
// function isClientSide() {
// return typeof window !== "undefined";
// }
// // Safely get item from localStorage
// function getFromLocalStorage(key, defaultValue) {
// if (isClientSide()) {
// return localStorage.getItem(key)
// ? JSON.parse(localStorage.getItem(key))
// : defaultValue;
// }
// return defaultValue;
// }
// // Safely set item to localStorage
// function setToLocalStorage(key, value) {
// if (isClientSide()) {
// localStorage.setItem(key, JSON.stringify(value));
// }
// }
// // Define the updated Message interface
// export interface Message {
// text: string;
// timestamp: string;
// sender: string;
// type: string;
// composite?: object | null; // New field
// }
// // Load messages from localStorage or set an empty array if not available
// const initialMessages = getFromLocalStorage('chat-messages', []);
// // Convert the array to a writable store
// export const messages = writable(initialMessages);
// // Subscribe to messages store to watch for changes and save them to localStorage
// messages.subscribe(currentMessages => {
// setToLocalStorage('chat-messages', currentMessages);
// });
// export function createMessage(messageData) {
// const currentDate = new Date().toLocaleString();
// const newMessageObj = {
// text: messageData.text,
// timestamp: currentDate,
// sender: messageData.sender,
// type: messageData.type,
// composite: messageData.composite || null // New field
// };
// messages.update(oldMessages => [...oldMessages, newMessageObj]);
// }
// export function clearMessages() {
// messages.set([]);
// }
// // Dummy messages
// export const messagesList: Message[] = [
// { text: "Hello there!", timestamp: new Date().toLocaleString(), sender: "John", type: "text" },
// { text: "How are you?", timestamp: new Date().toLocaleString(), sender: "Alice", type: "text" },
// // Add more dummy messages here with the timestamp and sender properties
// ];

View File

@ -34,6 +34,22 @@ function getRecursiveServiceFiles(dir) {
return files; return files;
} }
function getRecursiveDataFiles(dir) {
const dirents = fs.readdirSync(dir, { withFileTypes: true });
const files = Array.from(dirents).flatMap((dirent) => {
const res = resolve(dir, dirent.name);
if (dirent.isDirectory()) {
return getRecursiveDataFiles(res);
} else if (res.endsWith('.ts')) {
return [res];
} else {
return [];
}
});
return files;
}
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
sveltekit(), sveltekit(),
@ -84,6 +100,30 @@ export default defineConfig({
} }
return null; return null;
} }
},
{
name: 'data-sources-resolver',
resolveId(source) {
if (source === 'virtual:data-sources-list') return source;
return null;
},
load(id) {
if (id === 'virtual:data-sources-list') {
const dataDir = resolve(__dirname, 'src/lib/data');
const dataFiles = getRecursiveServiceFiles(dataDir); // Use the same function as before
const dataSources = dataFiles.map(file =>
file
.replace(dataDir, '')
.replace(/\.ts$/, '')
.replace(/\\/g, '/') // Fix Windows path separators
.slice(1) // Remove leading "/"
);
return `export default ${JSON.stringify(dataSources)};`;
}
return null;
}
} }
], ],
test: { test: {