gsoutz
gsoutz
SSolidJS
Created by gsoutz on 10/5/2024 in #support
Invalid Frame Header only on production build websockets
I wrote this simple tutorial, only to realize it's a minimum reproducible example that demonstrates the bug: Steps to Reproduce:
git clone https://github.com/eguneys/solidstart-websockets-chat-tutorial

pnpm install
pnpm build

node ./output/server/index.mjs
git clone https://github.com/eguneys/solidstart-websockets-chat-tutorial

pnpm install
pnpm build

node ./output/server/index.mjs
Look at the websocket connection in the network tab, see it breaks with this error: Invalid Frame Header. But if you run, pnpm dev The error is gone. Please fix this "very" obscure error asap, or it's a very shame as I produced it very quickly while writing my tutorial.
3 replies
SSolidJS
Created by gsoutz on 10/5/2024 in #support
production build runs my code twice
I have a solid start app I coded some things. When I run pnpm dev it works fine. But when I do pnpm build, and node .output/index.mjs it logs the things twice on the server log, and my websocket connection breaks with invalid frame header, which is likely related to this running twice thing.
1 replies
SSolidJS
Created by gsoutz on 10/5/2024 in #support
cache doesnt revalidate inside websocket on('message')
I have this:
await make_game_move({ id: this.game_id, board, status, sans })

await revalidate(['get_game', 'get_pov'])

let asdf = await getGame(this.game_id)
console.log('after revalidate', this.game_id, 'sans', asdf!.sans)


this.publish_peers({ t: 'move', d: uci })
await make_game_move({ id: this.game_id, board, status, sans })

await revalidate(['get_game', 'get_pov'])

let asdf = await getGame(this.game_id)
console.log('after revalidate', this.game_id, 'sans', asdf!.sans)


this.publish_peers({ t: 'move', d: uci })
after await revalidate , getGame still returns the old value. This is running inside websocket's on('message').
4 replies
SSolidJS
Created by gsoutz on 10/4/2024 in #support
"use server" doesn't work if put at the top of the file
I have this code which causes reactive triggers when user is changed by an useAction:
import { cache } from "@solidjs/router";
import { useSession } from "vinxi/http";
import { create_user, drop_user_by_id, new_user, Profile, profile_by_username, User, user_by_id } from "./routes/db";

export type UserSession = {
user_id: string
}

export const getSession = async () => {
"use server"
return await useSession<UserSession>({
password: process.env.SESSION_SECRET ?? 'secret_hash_key_placeholder_32_keys'
})
}


export const getUser = cache(async (): Promise<User> => {
"use server"
const session = await getSession()
return user
}, 'get_user')
import { cache } from "@solidjs/router";
import { useSession } from "vinxi/http";
import { create_user, drop_user_by_id, new_user, Profile, profile_by_username, User, user_by_id } from "./routes/db";

export type UserSession = {
user_id: string
}

export const getSession = async () => {
"use server"
return await useSession<UserSession>({
password: process.env.SESSION_SECRET ?? 'secret_hash_key_placeholder_32_keys'
})
}


export const getUser = cache(async (): Promise<User> => {
"use server"
const session = await getSession()
return user
}, 'get_user')
but if I remove the "use server" from inside functions and place it at the top of the file, The getUser() doesn't reactive update anymore, it breaks.
5 replies
SSolidJS
Created by gsoutz on 10/3/2024 in #support
How do I do something after a redirect, like reload the page, or in this case reconnect a websocket?
there is no redirect reload, or some kind of hook that gets called after a redirect has happened to the same dynamic route with different params.
10 replies
SSolidJS
Created by gsoutz on 10/3/2024 in #support
Should I destroy and create a new websocket connection on each page?
Or keep the existing connection throughout different pages, and somehow figure out which page should I handle by different means. I solved all my websocket problems, now this question come to my head, because it takes a split second more to open up the connection and be ready.
3 replies
SSolidJS
Created by gsoutz on 10/3/2024 in #support
How to crossws websocket Resolver API access getSession?
I am trying to use WebSockets with crossws, I have this piece of code at the beginning:
const ws = crossws({
async resolve(req) {
let user = await getUser()
return {
open(peer) {
let i = dispatch_peer(user, peer)
i?.join()
}
message(peer) {
const ws = crossws({
async resolve(req) {
let user = await getUser()
return {
open(peer) {
let i = dispatch_peer(user, peer)
i?.join()
}
message(peer) {
getUser() uses "use server" and getSession kind of things, so it needs some Context I think. But this getUser() line throws:
file:///workspaces/duckchess25/node_modules/.pnpm/[email protected]/node_modules/unctx/dist/index.mjs:31
throw new Error("Context is not available");
^

Error: Context is not available
at Object.use (file:///workspaces/duckchess25/node_modules/.pnpm/[email protected]/node_modules/unctx/dist/index.mjs:31:15)
at getEvent (/workspaces/duckchess25/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected][email protected][email protected]/node_modules/vinxi/runtime/http.js:301:33)
at getHTTPEv
file:///workspaces/duckchess25/node_modules/.pnpm/[email protected]/node_modules/unctx/dist/index.mjs:31
throw new Error("Context is not available");
^

Error: Context is not available
at Object.use (file:///workspaces/duckchess25/node_modules/.pnpm/[email protected]/node_modules/unctx/dist/index.mjs:31:15)
at getEvent (/workspaces/duckchess25/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected][email protected][email protected]/node_modules/vinxi/runtime/http.js:301:33)
at getHTTPEv
I specifically wanted to put the getUser() there, so I don't have to use it inside message(peer), each time message is exchanged getUser is queried. So what is the proper way to have access to user object taken from the session and the database, so it's readily available on websocket handlers?
3 replies
SSolidJS
Created by gsoutz on 10/2/2024 in #support
I can't load app.scss inside app.tsx and load globally on all pages
app.tsx has this: import "./app.scss"; Which sets the background color of the page. If I load the home page this style is loaded. But If I navigate to profile then navigate back to home page, styling is gone. as this app.scss has never been imported. If I put this import like this on Home.tsx
import "~/app.scss";
import './Home.scss'
import "~/app.scss";
import './Home.scss'
like this, it loads on every case as expected.
2 replies
SSolidJS
Created by gsoutz on 10/2/2024 in #support
__vite-browser-external:node:async_hooks:3 Uncaught Error: Module "node:async_hooks" has been extern
vite-browser-external:node:async_hooks:3 Uncaught Error: Module "node:async_hooks" has been externalized for browser compatibility. Cannot access "node:async_hooks.AsyncLocalStorage" in client code. See https://vitejs.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility for more details. at Object.get (vite-browser-external:node:async_hooks:3:11) at http.js:71:53 Here's my code looks like:
export const getUser = async (): Promise<User> => {
"use server"

const session = await getSession()

const user_id = session.data.user_id
let user: User | undefined
if (user_id) {
user = await user_by_id(user_id)
}

if (user) {
return user
}

user = create_user()

await new_user(user)
await session.update((d: UserSession) => ({ user_id: user.user_id }))
return user
}


export default function App() {

return (
<Router
root={props => (
<MetaProvider>
<Title>SolidStart - Basic</Title>
<Nav/>
<Suspense>{props.children}</Suspense>
</MetaProvider>
)}
>
<FileRoutes />
</Router>
);
}

const Nav = () => {
const user = createAsync(() => getUser(), { deferStream: true })

return (<>
<nav>
<a class='logo' href="/">duckchess<span>.org</span></a>
<Suspense>
<Show when={user()}>{user =>
<A class='dasher' href={`/u/${user().username}`}>{user().username}</A>
}</Show>
</Suspense>
</nav>
</>)
}
export const getUser = async (): Promise<User> => {
"use server"

const session = await getSession()

const user_id = session.data.user_id
let user: User | undefined
if (user_id) {
user = await user_by_id(user_id)
}

if (user) {
return user
}

user = create_user()

await new_user(user)
await session.update((d: UserSession) => ({ user_id: user.user_id }))
return user
}


export default function App() {

return (
<Router
root={props => (
<MetaProvider>
<Title>SolidStart - Basic</Title>
<Nav/>
<Suspense>{props.children}</Suspense>
</MetaProvider>
)}
>
<FileRoutes />
</Router>
);
}

const Nav = () => {
const user = createAsync(() => getUser(), { deferStream: true })

return (<>
<nav>
<a class='logo' href="/">duckchess<span>.org</span></a>
<Suspense>
<Show when={user()}>{user =>
<A class='dasher' href={`/u/${user().username}`}>{user().username}</A>
}</Show>
</Suspense>
</nav>
</>)
}
2 replies
SSolidJS
Created by gsoutz on 10/2/2024 in #support
What is wrong with Math.random create Signal
This code:
const [name, set_name] = createSignal(`Guest ${Math.floor(Math.random() * 10)}`)
const [name, set_name] = createSignal(`Guest ${Math.floor(Math.random() * 10)}`)
produces different values on interface and in createEffect log, what is going on?
8 replies
SSolidJS
Created by gsoutz on 10/2/2024 in #support
Websockets in SolidStart Example
I am writing a tutorial for solidhack about how to use WebSocket's in SolidStart, I based my example on this example repo https://github.com/peerreynders/solid-start-ws-demo . Is this still the best practice, or there is a better way?
2 replies
SSolidJS
Created by gsoutz on 7/19/2024 in #support
Cant set signal from getting another signal typescript error
function update<T>(target: Accessor<T | undefined>) {

let [current, set_current] = createSignal<T | undefined>(undefined)

set_current(target())
}
function update<T>(target: Accessor<T | undefined>) {

let [current, set_current] = createSignal<T | undefined>(undefined)

set_current(target())
}
No overload matches this call.
The last overload gave the following error.
Argument of type 'T | undefined' is not assignable to parameter of type 'Exclude<T, Function> | ((prev: T | undefined) => T | undefined) | undefined'.
Type 'T' is not assignable to type 'Exclude<T, Function> | ((prev: T | undefined) => T | undefined) | undefined'.(2769)
signal.d.ts(109, 3): The last overload is declared here.
(parameter) target: () => T | undefined
No overload matches this call.
The last overload gave the following error.
Argument of type 'T | undefined' is not assignable to parameter of type 'Exclude<T, Function> | ((prev: T | undefined) => T | undefined) | undefined'.
Type 'T' is not assignable to type 'Exclude<T, Function> | ((prev: T | undefined) => T | undefined) | undefined'.(2769)
signal.d.ts(109, 3): The last overload is declared here.
(parameter) target: () => T | undefined
https://playground.solidjs.com/anonymous/3218adfe-fd03-4d61-9763-02637001ca22
7 replies
SSolidJS
Created by gsoutz on 7/17/2024 in #support
Is there any examples of making a library with vite that exports a Solid.js Component.
I want to make one.
6 replies
SSolidJS
Created by gsoutz on 7/16/2024 in #support
createResource signal isn't trigger if undefined or null
let fetcher: Signal<number | undefined> = createSignal(3)

let r = createResource(fetcher, async (v) => console.log(v))

fetcher[1](undefined) // doesn't log anything
fetcher[1](null) // doesn't log anything
let fetcher: Signal<number | undefined> = createSignal(3)

let r = createResource(fetcher, async (v) => console.log(v))

fetcher[1](undefined) // doesn't log anything
fetcher[1](null) // doesn't log anything
Sometimes I want resource to return undefined, when the underlying signal goes undefined. That's how I like it. Why is this forbidden?.. If I change undefined with true it triggers as I expect it. but undefined makes more sense here.
3 replies
SSolidJS
Created by gsoutz on 7/16/2024 in #support
set signal batched intermediate sets are lost for animation
createEffect(() => console.log(count()))

set_count(undefined)
set_count(3)

set_count(5)
createEffect(() => console.log(count()))

set_count(undefined)
set_count(3)

set_count(5)
This logs only 5, but think about a scenario where I control the klasses of a div, with animation. first I want to reset the animation so I set the signal to undefined, then I set it to three to add the three klass, then five klass. how does this supposed to be done?
4 replies
SSolidJS
Created by gsoutz on 7/15/2024 in #support
Untrack has no effect but signal doesn't fire anyway
Take a look at this way of events:
createEffect(() => {
console.log('fix fix', this.roundn[0]())
})

createEffect(() => {
let n =untrack(() => this.roundn[0]())

if (n) {
console.log('ok test', n.flop[0].card)
}
})


createEffect(() => {
let n = this.roundn[0]()

if (n) {
console.log('not test', n.flop[0].card)
}
})
createEffect(() => {
console.log('fix fix', this.roundn[0]())
})

createEffect(() => {
let n =untrack(() => this.roundn[0]())

if (n) {
console.log('ok test', n.flop[0].card)
}
})


createEffect(() => {
let n = this.roundn[0]()

if (n) {
console.log('not test', n.flop[0].card)
}
})
I trigger an event, and this is the console.log output:
not test 7h
not test 7h
I mean ok test doesn't happen because I untracked roundn() but roundn also doesn't happen because fix fix doesn't log.
10 replies
SSolidJS
Created by gsoutz on 5/19/2024 in #support
What do I do if I have to wait for things to happen, meanwhile define extra state or what
this piece of code come up as crucial functionality all over the place for me, for an interactive application of solidjs
createEffect(on(uci, uci => {
set_uci(uci)
setTimeout(() => {
set_active_candidate_to_next_guess()
}, 1000)
}))
createEffect(on(uci, uci => {
set_uci(uci)
setTimeout(() => {
set_active_candidate_to_next_guess()
}, 1000)
}))
So I set something, and wait for user to acknowledge it, then I go to next state. While I am waiting some kind of pending state happening. Do I keep track of these waiting states, because I have some timing related bugs creeping in my code I don't know how to fix. Not considering waiting for some asynchronous processes on the way.
15 replies
SSolidJS
Created by gsoutz on 3/27/2024 in #support
How can I protect nothing ever breaks, while the setTimeout is waiting
tsx
createEffect(() => {
if (puzzle_lala().is_revealed && is_jump_to_next_puzzle_immediately()) {

setTimeout(() => {
on_next_puzzle()
}, 600)
}
})
tsx
createEffect(() => {
if (puzzle_lala().is_revealed && is_jump_to_next_puzzle_immediately()) {

setTimeout(() => {
on_next_puzzle()
}, 600)
}
})
And Yes, I don't want to check whether this has been triggered everywhere else.
2 replies
SSolidJS
Created by gsoutz on 3/18/2024 in #support
I've shot myself in the foot again.
Help. I don't know what signal is causing which effect or why they are triggered thrice on each change.
15 replies
SSolidJS
Created by gsoutz on 3/15/2024 in #support
How to decorators typescript signal
To template this out
_foo: Signal<number>

get foo() {
return _foo[0]()
}

set foo(_: number) {
_foo[1](_)
}

constructor() {
this._foo = createSignal(0)
}
_foo: Signal<number>

get foo() {
return _foo[0]()
}

set foo(_: number) {
_foo[1](_)
}

constructor() {
this._foo = createSignal(0)
}
18 replies