zimo
zimo
SSolidJS
Created by zimo on 8/14/2024 in #support
Cache server variable separately in db, server, front-end
So I have the idea to be able to "lock" my database for maintenance I sometimes do offline. My idea is thus to have a "locked" setting in a persistent settings table in my database. On startup, the server should read this setting and set a server-side variable based on it, let's called it isDbLocked. I would then like the front end to be able to read this server-side variable to disable some UI elements. An admin should then be able to change this variable through the UI. Which in turn tries to update the database. If successful, it updates the server-side variable, and thus the front end too (maybe makes a new explicit request here to update it). My question is how to do this in practice in SolidStart? I tried something like just having a .ts file with a isDbLocked variable, then an init function that queries the db on server init. But I can't just import and use isDbLocked probably... I would need to fetch it from the server? Should I createResource or "use server"? Also is this overly complicated? Should I just always make requests that always read the db and returns the setting instead of having an intermediate server-side variable? My idea was to reduce requests to the DB since we always know the value of isDbLocked. It's only ever changed when an admin changes it.
3 replies
SSolidJS
Created by zimo on 7/31/2024 in #support
Component with only <For /> in it removes all HTML children
I have this set up:
return <div
ref={mapElement}
>
<For each={mainStore.countries}>
{country => {
return <MapCountry country={country} />
}}
</For>
</div>
return <div
ref={mapElement}
>
<For each={mainStore.countries}>
{country => {
return <MapCountry country={country} />
}}
</For>
</div>
Where the outer div is used as a reference to attach a Mapbox-gl canvas element, along with some more HTML elements. But I also fill it with some components of my own "MapCountry". My problem is that when mainStore.countries is an empty list, Solid removes all children of my outer div, including the elements created by Mapbox-gl. My current work-around is to add a dummy element to the outer div:
return <div
ref={mapElement}
>
<For each={mainStore.countries}>
{country => {
return <MapCountry country={country} />
}}
</For>

{/* dummy element lol */}
<div />
</div>
return <div
ref={mapElement}
>
<For each={mainStore.countries}>
{country => {
return <MapCountry country={country} />
}}
</For>

{/* dummy element lol */}
<div />
</div>
Is this the best solution? Could I prevent solid from removing all items?
5 replies
SSolidJS
Created by zimo on 7/21/2024 in #support
Prisma integration example fails in build
Could someone help me try to reproduce a bug I get in the official npm init solid@latest? 1. npm init solid@latest 2. Select the following options: Solid-Start: Yes, TypeScript: Yes, template: "with-prisma" 3. cd into project folder 4. npm install 5. npx prisma generate 6. npx prisma migrate dev 7. npm run dev 8. Open "localhost:3000". Interact with the site. Register a user, login, logout. Observe correct behavior. 9. npm run build 10. node .output/server/index.mjs 11. Open "localhost:3000". Interact with the site. Register a user, login, logout. Observe it's impossible. Error: Invalid prisma.user.findUnique() invocation: The table main.User does not exist in the current database. I wrote an issue on the Prisma repo here: https://github.com/prisma/prisma/issues/24845 but I don't see other people with this error so it might be something in the Solid/Vinxi ecosystem.
7 replies
SSolidJS
Created by zimo on 7/20/2024 in #support
Generic yet obscure Vinxi error when compiling
┌──────────────────────────────────────┐
│ 📦 Compiling server-fns router... │
└──────────────────────────────────────┘
vinxi building router server-fns in http mode
vite v5.3.3 building SSR bundle for production...
✓ 0 modules transformed.
x Build failed in 53ms

ERROR Could not resolve entry module "$vinxi/handler/server-fns". 14:13:17

at getRollupError (/C:/projects/polandballworld/node_modules/rollup/dist/es/shared/parseAst.js:392:41)
at error (/C:/projects/polandballworld/node_modules/rollup/dist/es/shared/parseAst.js:388:42)
at ModuleLoader.loadEntryModule (/C:/projects/polandballworld/node_modules/rollup/dist/es/shared/node-entry.js:19092:20)
at async Promise.all (index 0)



ERROR Could not resolve entry module "$vinxi/handler/server-fns". 14:13:17
┌──────────────────────────────────────┐
│ 📦 Compiling server-fns router... │
└──────────────────────────────────────┘
vinxi building router server-fns in http mode
vite v5.3.3 building SSR bundle for production...
✓ 0 modules transformed.
x Build failed in 53ms

ERROR Could not resolve entry module "$vinxi/handler/server-fns". 14:13:17

at getRollupError (/C:/projects/polandballworld/node_modules/rollup/dist/es/shared/parseAst.js:392:41)
at error (/C:/projects/polandballworld/node_modules/rollup/dist/es/shared/parseAst.js:388:42)
at ModuleLoader.loadEntryModule (/C:/projects/polandballworld/node_modules/rollup/dist/es/shared/node-entry.js:19092:20)
at async Promise.all (index 0)



ERROR Could not resolve entry module "$vinxi/handler/server-fns". 14:13:17
How am I supposed to interpret and try to debug this error? Caused when npm run build
2 replies
SSolidJS
Created by zimo on 7/18/2024 in #support
"Cannot find module" for image files
Whenever I do something like
import favicon from "./assets/favicon.ico";
import favicon from "./assets/favicon.ico";
I get a TS error of
Cannot find module './assets/favicon.ico' or its corresponding type declarations.ts(2307)
Cannot find module './assets/favicon.ico' or its corresponding type declarations.ts(2307)
. Same goes for .module.css files, but .css imports correctly. I tried adding a declarations.d.ts file:
declare module '*.module.css' {
const classes: { [key: string]: string };
export default classes;
}

declare module '*.(png|ico|svg|jpg|jpeg|gif|bmp|tiff)' {
const value: string;
export default value;
}
declare module '*.module.css' {
const classes: { [key: string]: string };
export default classes;
}

declare module '*.(png|ico|svg|jpg|jpeg|gif|bmp|tiff)' {
const value: string;
export default value;
}
Which I import in tsconfig, restart the TS server but the error persists:
{
"compilerOptions": {
...
},
"include": ["src", "src/declarations.d.ts"]
}
{
"compilerOptions": {
...
},
"include": ["src", "src/declarations.d.ts"]
}
It all compiles fine and the files are found, it's just an annoying TS error. Any idea why this happens and how to fix this?
1 replies
SSolidJS
Created by zimo on 7/17/2024 in #support
Navigating through @solidjs/router doesn't load global app.css
No description
25 replies
SSolidJS
Created by zimo on 7/11/2024 in #support
css loads slowly (lazily?) causing ugly page for a few frames
I just tried upgrading to latest version of SolidStart and noticed this. Others seem to have noticed similar things in the past: https://discord.com/channels/722131463138705510/910635844119982080/1233478382482620532 https://github.com/solidjs/solid-start/pull/1423 (this issue have nice pictures demonstrating what's happening) That PR seems to be merged but it still happens to me. I did not experience this in some beta versions where only Vite was used. So I suspect it might be a Vinxi problem. Sample project for what I'm doing: https://github.com/zimonitrome/SolidStart-Prisma-AuthJS-example
5 replies
SSolidJS
Created by zimo on 7/10/2024 in #support
"[error] UnknownAction" on getSession() in AuthJS
Hello, I have tried to follow the example here on using @solid-mediakit/auth: https://www.npmjs.com/package/@solid-mediakit/auth#server-side I have implemented it as suggested but I am having trouble using getSession(). In previous versions I have used it in server-side db methods like this:
export const fetchCountryInfoServer = server$(async (countryId: string) => {
const session = await getSession(server$.request, authOptions);
const user = await getAndVerifyUser(session);

return await prisma.country.findFirst({ where: { userId: user.id } });
});
export const fetchCountryInfoServer = server$(async (countryId: string) => {
const session = await getSession(server$.request, authOptions);
const user = await getAndVerifyUser(session);

return await prisma.country.findFirst({ where: { userId: user.id } });
});
I have tried upgrading to something like:
export const fetchCountryInfoServer = async (countryId: string) => {
"use server"
const session = await getSession(getWebRequest(), authOptions);
const user = await getAndVerifyUser(session);

return await prisma.country.findFirst({ where: { userId: user.id } });
};
export const fetchCountryInfoServer = async (countryId: string) => {
"use server"
const session = await getSession(getWebRequest(), authOptions);
const user = await getAndVerifyUser(session);

return await prisma.country.findFirst({ where: { userId: user.id } });
};
And this is just called in a button onClick() method on my frontend:
const onClick = async () => {
const expandedCountry = await fetchCountryInfoServer(country.id);
// Assign to store...
};
const onClick = async () => {
const expandedCountry = await fetchCountryInfoServer(country.id);
// Assign to store...
};
But the problem is that I get the following fairly generic error:
[auth][error] UnknownAction: Cannot parse action at /api/auth/session. Read more at https://errors.authjs.dev#unknownaction
[auth][error] UnknownAction: Cannot parse action at /api/auth/session. Read more at https://errors.authjs.dev#unknownaction
6 replies
SSolidJS
Created by zimo on 4/11/2024 in #support
Delete key in store
How do I delete a key in a store? My store is typed so I can't simply set the value to undefined. Will I have to use the mutate helper, whatever it's called? I'm used to changing keys in a store by just doing setMyStore("my_key", value);
3 replies
SSolidJS
Created by zimo on 4/9/2024 in #support
Failed to execute 'replaceChild' on 'Node': The node to be replaced is not a child of this node.
I have a store:
export const [mainStore, setMainStore] = createStore<StoreType>({ countries: undefined });
export const [mainStore, setMainStore] = createStore<StoreType>({ countries: undefined });
of this type:
export type StoreType = {
countries?: FrontEndCountry[]
}

export interface FrontEndCountry {
id: string
name: string
type?: string | null
parentCountryId?: string | null
subtitle?: string | null
description?: string | null
countrySprites: FrontEndSprite[]
}

export interface FrontEndSprite {
lat: number
lng: number
z: number
scale: number
mapName: string
countryId: string
}
export type StoreType = {
countries?: FrontEndCountry[]
}

export interface FrontEndCountry {
id: string
name: string
type?: string | null
parentCountryId?: string | null
subtitle?: string | null
description?: string | null
countrySprites: FrontEndSprite[]
}

export interface FrontEndSprite {
lat: number
lng: number
z: number
scale: number
mapName: string
countryId: string
}
I'm trying to render only part of these countries, or rather their sprites. I filter them out and render them like this:
<For each={mainStore.countries?.filter(c => {

const countryIsExtra = !countryNames.includes(c.name);
const extraSelected = characters().includes("extra");

if (countryIsExtra && !extraSelected)
return false;

const countrySelected = characters().includes("countries");
if (!countryIsExtra && !countrySelected)
return false;

const hasSelectedSkin = c.countrySprites.filter(s => s.mapName === mapSkin()).length > 0;
if (!hasSelectedSkin)
return false;

return true;
})}>
{(country, ix) => {
return <MapCountry countrySprite={country.countrySprites.filter(s => s.mapName === mapSkin())[0]} />
}}
</For>
<For each={mainStore.countries?.filter(c => {

const countryIsExtra = !countryNames.includes(c.name);
const extraSelected = characters().includes("extra");

if (countryIsExtra && !extraSelected)
return false;

const countrySelected = characters().includes("countries");
if (!countryIsExtra && !countrySelected)
return false;

const hasSelectedSkin = c.countrySprites.filter(s => s.mapName === mapSkin()).length > 0;
if (!hasSelectedSkin)
return false;

return true;
})}>
{(country, ix) => {
return <MapCountry countrySprite={country.countrySprites.filter(s => s.mapName === mapSkin())[0]} />
}}
</For>
In short you can toggle between different mapSkin() and different characters(), both of which currently have two settings. It works OK when you go from no characters selected to a few selected, or when you seemingly replace all the sprites, but as soon as the resulting list expands or contracts I get the omnious error:
Error: Failed to execute 'replaceChild' on 'Node': The node to be replaced is not a child of this node.
Error: Failed to execute 'replaceChild' on 'Node': The node to be replaced is not a child of this node.
I have had this error for a few weeks now. Am I using stores incorrectly?
7 replies
SSolidJS
Created by zimo on 10/9/2023 in #support
Use :before and :after inline?
Any way to use pseudo-classes in Solid without a separate css file?
2 replies
SSolidJS
Created by zimo on 10/9/2023 in #support
Can I react/listen on store changes?
I a variable I have been explicitly listening on changes to:
createEffect(on(mySignal, () => {
doThing();
}));
createEffect(on(mySignal, () => {
doThing();
}));
Now I also have a store. But I can't do on([mySignal, myStore], ...) Is there another way?
3 replies
SSolidJS
Created by zimo on 6/14/2023 in #support
Remove item from store list?
I have tried:
const itemId = 5;
setMainStore(
"mylist",
produce((mylist: number[] | undefined) =>
mylist?.filter(item => item.id !== itemId.id
)
)
console.log(mainStore.mylist!);
const itemId = 5;
setMainStore(
"mylist",
produce((mylist: number[] | undefined) =>
mylist?.filter(item => item.id !== itemId.id
)
)
console.log(mainStore.mylist!);
and
const itemId = 5;
setMainStore(
"mylist",
produce((mylist: number[] | undefined) =>
mylist?.slice(mylist?.findIndex(item => item.id === itemId), 1)
)
)
console.log(mainStore.mylist!);
const itemId = 5;
setMainStore(
"mylist",
produce((mylist: number[] | undefined) =>
mylist?.slice(mylist?.findIndex(item => item.id === itemId), 1)
)
)
console.log(mainStore.mylist!);
but neither seem to change the list at all.
30 replies
SSolidJS
Created by zimo on 6/5/2023 in #support
Mutate createServerData$ resource
I have a route component that renders countries:
export function routeData() {
const countries = createServerData$(() => prisma.country.findMany());
const session = createServerData$(async (_, event) => {
return getSession(event.request, authOptions);
});

return {countries, session}
}

export default () => {
// Get data at start of app
const {countries, session} = useRouteData<typeof routeData>();


return (
<main>
<Show when={countries()} fallback={"Loading..."} keyed>
{(countries) => (
<For each={countries} fallback={"No items"}>
{country => {
const coordsFormatted = `(lat=${country.lat}, lng=${country.lng})`;
return <div>
<h3>{country.name}</h3>
<p>{coordsFormatted}</p>
</div>
}}
</For>
)}
</Show>
</main>
);
}
export function routeData() {
const countries = createServerData$(() => prisma.country.findMany());
const session = createServerData$(async (_, event) => {
return getSession(event.request, authOptions);
});

return {countries, session}
}

export default () => {
// Get data at start of app
const {countries, session} = useRouteData<typeof routeData>();


return (
<main>
<Show when={countries()} fallback={"Loading..."} keyed>
{(countries) => (
<For each={countries} fallback={"No items"}>
{country => {
const coordsFormatted = `(lat=${country.lat}, lng=${country.lng})`;
return <div>
<h3>{country.name}</h3>
<p>{coordsFormatted}</p>
</div>
}}
</For>
)}
</Show>
</main>
);
}
I want to update countries() locally when pressing a button (and also on the db but I think I know how) and re-render the component. How would I go about doing this? Something like this, but getting and setting the resource on the server as well https://playground.solidjs.com/anonymous/fa0e93a0-5c83-44cc-913b-2801d96e1363
2 replies
SSolidJS
Created by zimo on 6/4/2023 in #support
call `createServerData$` outside Route?
Can I call createServerData$ outside of a Route? I want to put it in a header that is outside of my routes. Do I need to create a "master route" that has children?
5 replies
SSolidJS
Created by zimo on 5/29/2023 in #support
Joining SolidJS Vite app with a rest api as single app
Hello, I'm building a simple front end with the default SolidJS+Vite template. I call this the client. The client need to call some things from a rest API server, so I currently have a second Node app running. Let's call this "server". The server uses Express to do some simple file management. This is all fine and well. When I'm building for production I first build the client into /dist. I then move the /dist folder into the server and build the server into the final /dist for production. This works, but I think it's a little ugly. Preferably I would want to have one single Node project with a single package.json, but that still has hot reloading. How is this normally done?
2 replies