MaveriX89
MaveriX89
Explore posts from servers
SSolidJS
Created by MaveriX89 on 1/22/2025 in #support
Exception thrown when invoking useNavigate within Router root layout
Just adding more additional context here. The NavbarLink components are just <A> elements from @solidjs/router wrapped under <li> tags. And for reference, here is my Login.tsx:
import { action, createAsync, redirect, useNavigate, useSubmission } from "@solidjs/router";
import { createEffect, Show } from "solid-js";

import { Button } from "~/components/ui/button";
import { TextField, TextFieldInput, TextFieldLabel } from "~/components/ui/text-field";

import Logo from "../assets/logo_login.svg";
import { authClient } from "../lib/auth-client";
import { getAuthState } from "../lib/queries";
import { convertToRecord, isNil } from "../lib/utils";

type SignInForm = {
readonly username: string;
readonly password: string;
};

const authenticate = action(async (data: FormData) => {
const response = await authClient.signIn.username(convertToRecord<SignInForm>(data));

if (response.error) throw new Error(response.error.message);

throw redirect("/dashboard");
});

export default function SignIn() {
const navigate = useNavigate();
const auth = createAsync(() => getAuthState());
const authenticating = useSubmission(authenticate);

createEffect(() => {
if (!isNil(auth())) {
navigate("/dashboard");
}
});

return (
<div class="h-full flex flex-col items-center justify-center gap-6">
<img src={Logo} width="200" />
<form action={authenticate} method="post" class="flex flex-col gap-6 w-[300px]">
<TextField>
<TextFieldLabel class="mb-2">Username</TextFieldLabel>
<TextFieldInput name="username" autocomplete="username" />
</TextField>
<TextField>
<TextFieldLabel class="mb-2">Password</TextFieldLabel>
<TextFieldInput name="password" type="password" autocomplete="current-password" />
</TextField>
<Button class="button" type="submit" disabled={authenticating.pending}>
{authenticating.pending ? "Authenticating..." : "Sign In"}
</Button>
</form>
<Show when={authenticating.error}>
<p style={{ color: "red" }} role="alert" id="error-message">
{authenticating.error?.message}
</p>
</Show>
</div>
);
}
import { action, createAsync, redirect, useNavigate, useSubmission } from "@solidjs/router";
import { createEffect, Show } from "solid-js";

import { Button } from "~/components/ui/button";
import { TextField, TextFieldInput, TextFieldLabel } from "~/components/ui/text-field";

import Logo from "../assets/logo_login.svg";
import { authClient } from "../lib/auth-client";
import { getAuthState } from "../lib/queries";
import { convertToRecord, isNil } from "../lib/utils";

type SignInForm = {
readonly username: string;
readonly password: string;
};

const authenticate = action(async (data: FormData) => {
const response = await authClient.signIn.username(convertToRecord<SignInForm>(data));

if (response.error) throw new Error(response.error.message);

throw redirect("/dashboard");
});

export default function SignIn() {
const navigate = useNavigate();
const auth = createAsync(() => getAuthState());
const authenticating = useSubmission(authenticate);

createEffect(() => {
if (!isNil(auth())) {
navigate("/dashboard");
}
});

return (
<div class="h-full flex flex-col items-center justify-center gap-6">
<img src={Logo} width="200" />
<form action={authenticate} method="post" class="flex flex-col gap-6 w-[300px]">
<TextField>
<TextFieldLabel class="mb-2">Username</TextFieldLabel>
<TextFieldInput name="username" autocomplete="username" />
</TextField>
<TextField>
<TextFieldLabel class="mb-2">Password</TextFieldLabel>
<TextFieldInput name="password" type="password" autocomplete="current-password" />
</TextField>
<Button class="button" type="submit" disabled={authenticating.pending}>
{authenticating.pending ? "Authenticating..." : "Sign In"}
</Button>
</form>
<Show when={authenticating.error}>
<p style={{ color: "red" }} role="alert" id="error-message">
{authenticating.error?.message}
</p>
</Show>
</div>
);
}
I make heavy use of the getAuthState query which you can see here:
import { query } from "@solidjs/router";

import { authClient } from "./auth-client";
import { isNil } from "./utils";

export const getAuthState = query(async () => {
const session = await authClient.getSession();

return isNil(session) || isNil(session.data)
? null
: {
user: session.data.user,
session: session.data.session,
error: session.error,
};
}, "authState");
import { query } from "@solidjs/router";

import { authClient } from "./auth-client";
import { isNil } from "./utils";

export const getAuthState = query(async () => {
const session = await authClient.getSession();

return isNil(session) || isNil(session.data)
? null
: {
user: session.data.user,
session: session.data.session,
error: session.error,
};
}, "authState");
From the looks of it, I do see the url change in my app showing that it went to /login -- however, everytime it does, the <ErrorBoundary> fallback component kicks in and displays instead of the Login page I defined above due to that thrown exception.
2 replies
SSolidJS
Created by MaveriX89 on 1/21/2025 in #support
SolidJS SPA with Better Auth
Yeah, this worked out in the end:
const signIn = action(async (data: FormData) => {
const response = await authClient.signIn.username(convertToRecord<SignInForm>(data));

if (response.error) throw new Error(response.error.message);

throw redirect("/home");
});
const signIn = action(async (data: FormData) => {
const response = await authClient.signIn.username(convertToRecord<SignInForm>(data));

if (response.error) throw new Error(response.error.message);

throw redirect("/home");
});
5 replies
SSolidJS
Created by MaveriX89 on 1/21/2025 in #support
SolidJS SPA with Better Auth
Gotcha -- let me see if Better Auth supports the non-callback expression for the signIn API call.
5 replies
SSolidJS
Created by MaveriX89 on 1/13/2025 in #support
Getting UnhandledPromiseRejection in Solid Start server function that stops dev server
Thanks for all your help and input in this thread. You've been incredibly invaluable. Yeah, I figured that I would lose single flight mutations in this road. That's a bullet I'm gonna have to bite. I've been fighting Solid Start way too much over these past few days over authenticated routes and how to properly manage them. Just my two cents, I feel that the documentation needs to be improved in perhaps adding examples around this use-case of properly handling protected routes within Solid Start.
33 replies
SSolidJS
Created by MaveriX89 on 1/13/2025 in #support
Getting UnhandledPromiseRejection in Solid Start server function that stops dev server
@peerreynders btw, do I also lose the ability to use action from Solid Router in my Elysia + Solid SPA approach?
33 replies
SSolidJS
Created by MaveriX89 on 1/13/2025 in #support
Getting UnhandledPromiseRejection in Solid Start server function that stops dev server
Only downside to going vanilla like that is that I'm not able to make use of the Data APIs within @solid/router if I'm not mistaken
33 replies
SSolidJS
Created by MaveriX89 on 1/13/2025 in #support
Getting UnhandledPromiseRejection in Solid Start server function that stops dev server
Yeah, it's an interesting problem...it's unfortunately blocking me from using Solid Start because of it. I may just pivot to doing a vanilla Solid SPA with an Elysia backend server if I'm not able to resolve the issue
33 replies
SSolidJS
Created by MaveriX89 on 1/13/2025 in #support
Getting UnhandledPromiseRejection in Solid Start server function that stops dev server
Yeah, this is all happening on my /login route page. I'm basically submitting an empty form and testing my failure/error path in my code.
33 replies
SSolidJS
Created by MaveriX89 on 1/13/2025 in #support
Getting UnhandledPromiseRejection in Solid Start server function that stops dev server
I'm all new to this myself in using Solid Start for the first time -- apologies if I'm not explaining things correctly. Basically, when I comment out that line where I return the Error object in my log in server function, the dev server doesn't croak and die. When I keep it and see it run, I actually see the error message appear on my UI that the Error returned, but the dev server dies once it appears. I took that as an indication that something perhaps went wrong on the server side and not client side 🤔
33 replies
SSolidJS
Created by MaveriX89 on 1/13/2025 in #support
Getting UnhandledPromiseRejection in Solid Start server function that stops dev server
This is what I see from the response from server_
;0x0000085a;
((self.$R = self.$R || {})["server-fn:0"] = [],
($R => $R[0] = {
"user[]": $R[1] = ($R[2] = (s, f, p) => ((p = new Promise( (a, b) => {
s = a,
f = b
}
)).s = s,
p.f = f,
p))(),
_$value: $R[3] = Object.assign(new Error("Usernames must be at least 3 characters long"), {
stack: "Error: Usernames must be at least 3 characters long\n at loginOrRegister2 (/Users/dsanchez/Developer/github/dsanchez/time-tracker/src/api/server.ts:66:12)\n at eval (/Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/@solidjs/start/dist/runtime/server-fns-runtime.js:29:19)\n at AsyncLocalStorage.run (node:internal/async_local_storage/async_hooks:91:14)\n at Module.provideRequestEvent (file:///Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/solid-js/web/storage/dist/storage.js:7:14)\n at Object.apply (/Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/@solidjs/start/dist/runtime/server-fns-runtime.js:28:36)\n at eval (/Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/@solidjs/start/dist/runtime/server-handler.js:110:14)\n at AsyncLocalStorage.run (node:internal/async_local_storage/async_hooks:91:14)\n at Module.provideRequestEvent (file:///Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/solid-js/web/storage/dist/storage.js:7:14)\n at handleServerFunction (/Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/@solidjs/start/dist/runtime/server-handler.js:103:46)\n at process.processTicksAndRejections (node:internal/process/task_queues:105:5)\n at async _callHandler (file:///Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/h3/dist/index.mjs:1837:16)\n at async file:///Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/h3/dist/index.mjs:1978:19\n at async Object.callAsync (file:///Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/unctx/dist/index.mjs:72:16)\n at async Server.toNodeHandle (file:///Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/h3/dist/index.mjs:2270:7)"
})
})($R["server-fn:0"]));
0x000000e3;
($R => ($R[9] = (p, d) => {
p.f(d),
p.status = "failure",
p.value = d;
delete p.s;
delete p.f
}
)($R[1], $R[4] = new Response(null,$R[5] = {
headers: $R[6] = new Headers($R[7] = [$R[8] = ["location", "/login"]]),
status: 302,
statusText: ""
})))($R["server-fn:0"])
;0x0000085a;
((self.$R = self.$R || {})["server-fn:0"] = [],
($R => $R[0] = {
"user[]": $R[1] = ($R[2] = (s, f, p) => ((p = new Promise( (a, b) => {
s = a,
f = b
}
)).s = s,
p.f = f,
p))(),
_$value: $R[3] = Object.assign(new Error("Usernames must be at least 3 characters long"), {
stack: "Error: Usernames must be at least 3 characters long\n at loginOrRegister2 (/Users/dsanchez/Developer/github/dsanchez/time-tracker/src/api/server.ts:66:12)\n at eval (/Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/@solidjs/start/dist/runtime/server-fns-runtime.js:29:19)\n at AsyncLocalStorage.run (node:internal/async_local_storage/async_hooks:91:14)\n at Module.provideRequestEvent (file:///Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/solid-js/web/storage/dist/storage.js:7:14)\n at Object.apply (/Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/@solidjs/start/dist/runtime/server-fns-runtime.js:28:36)\n at eval (/Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/@solidjs/start/dist/runtime/server-handler.js:110:14)\n at AsyncLocalStorage.run (node:internal/async_local_storage/async_hooks:91:14)\n at Module.provideRequestEvent (file:///Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/solid-js/web/storage/dist/storage.js:7:14)\n at handleServerFunction (/Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/@solidjs/start/dist/runtime/server-handler.js:103:46)\n at process.processTicksAndRejections (node:internal/process/task_queues:105:5)\n at async _callHandler (file:///Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/h3/dist/index.mjs:1837:16)\n at async file:///Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/h3/dist/index.mjs:1978:19\n at async Object.callAsync (file:///Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/unctx/dist/index.mjs:72:16)\n at async Server.toNodeHandle (file:///Users/dsanchez/Developer/github/dsanchez/time-tracker/node_modules/h3/dist/index.mjs:2270:7)"
})
})($R["server-fn:0"]));
0x000000e3;
($R => ($R[9] = (p, d) => {
p.f(d),
p.status = "failure",
p.value = d;
delete p.s;
delete p.f
}
)($R[1], $R[4] = new Response(null,$R[5] = {
headers: $R[6] = new Headers($R[7] = [$R[8] = ["location", "/login"]]),
status: 302,
statusText: ""
})))($R["server-fn:0"])
33 replies
SSolidJS
Created by MaveriX89 on 1/13/2025 in #support
Getting UnhandledPromiseRejection in Solid Start server function that stops dev server
Judging from the other post, could the problem be in me using getUser in some premature way? Below is my app's root layout
// @refresh reload
import { Router, A, createAsync, RouteSectionProps } from "@solidjs/router";
import { FileRoutes } from "@solidjs/start/router";
import { ParentProps, Show, Suspense } from "solid-js";
import { getUser } from "~/api";
import Logo from "./assets/logo.svg";
import { CircleUser } from "lucide-solid";
import "./app.css";

type User = {
readonly username: string;
}

type NavbarProps = {
readonly user: User;
}

const Navbar = (props: NavbarProps) => {
return (
<header class="text-white bg-slate-700 p-1 flex flex-row gap-2">
<div class="flex gap-1">
<img src={Logo} width="20" />
<p>Time Tracker</p>
</div>
<nav class="flex flex-row">
<A href="/">Dashboard</A>
</nav>
<div class="ml-auto flex items-center">
<CircleUser class="ml-auto" height={18} stroke-width={1} />
<p>{props.user.username}</p>
</div>
</header>
);
};

const MainContent = (props: ParentProps<{ class: string }>) => (
<main class={props.class}>
<Suspense>{props.children}</Suspense>
</main>
)

const RootLayout = (props: RouteSectionProps<unknown>) => {
const user = createAsync(async () => getUser(), { deferStream: true });

return (
<Suspense>
<Show when={user()} fallback={<MainContent class="h-screen">{props.children}</MainContent>}>
<div class="h-screen grid grid-rows-[auto_1fr]">
<Navbar user={user() as User} />
<MainContent class="h-full">{props.children}</MainContent>
</div>
</Show>
</Suspense>
)
};

export default function App() {
return (
<Router root={RootLayout}>
<FileRoutes />
</Router>
);
}
// @refresh reload
import { Router, A, createAsync, RouteSectionProps } from "@solidjs/router";
import { FileRoutes } from "@solidjs/start/router";
import { ParentProps, Show, Suspense } from "solid-js";
import { getUser } from "~/api";
import Logo from "./assets/logo.svg";
import { CircleUser } from "lucide-solid";
import "./app.css";

type User = {
readonly username: string;
}

type NavbarProps = {
readonly user: User;
}

const Navbar = (props: NavbarProps) => {
return (
<header class="text-white bg-slate-700 p-1 flex flex-row gap-2">
<div class="flex gap-1">
<img src={Logo} width="20" />
<p>Time Tracker</p>
</div>
<nav class="flex flex-row">
<A href="/">Dashboard</A>
</nav>
<div class="ml-auto flex items-center">
<CircleUser class="ml-auto" height={18} stroke-width={1} />
<p>{props.user.username}</p>
</div>
</header>
);
};

const MainContent = (props: ParentProps<{ class: string }>) => (
<main class={props.class}>
<Suspense>{props.children}</Suspense>
</main>
)

const RootLayout = (props: RouteSectionProps<unknown>) => {
const user = createAsync(async () => getUser(), { deferStream: true });

return (
<Suspense>
<Show when={user()} fallback={<MainContent class="h-screen">{props.children}</MainContent>}>
<div class="h-screen grid grid-rows-[auto_1fr]">
<Navbar user={user() as User} />
<MainContent class="h-full">{props.children}</MainContent>
</div>
</Show>
</Suspense>
)
};

export default function App() {
return (
<Router root={RootLayout}>
<FileRoutes />
</Router>
);
}
Does anything look unexpected here?
33 replies
SSolidJS
Created by MaveriX89 on 1/13/2025 in #support
Getting UnhandledPromiseRejection in Solid Start server function that stops dev server
Ah, that's funny -- I think that issue is the same exact problem I'm facing. In my case, the success path works fine without a problem. Haven't noticed any issues when logging in successfully. It only is the path where I return a new Error() in the code path for logging in on the server.
33 replies
SSolidJS
Created by MaveriX89 on 1/13/2025 in #support
Getting UnhandledPromiseRejection in Solid Start server function that stops dev server
Just not sure why when I invoke the error path (e.g. submitting without username and password) while in dev mode with my dev server running, the failure path on the server side chokes with the unhandled exception and shuts down my dev server which is not a graceful way to handle that. Seems like the wrong behavior to me. Not sure if it's something that I'm doing wrong from a workflow perspective / component design.
33 replies
SSolidJS
Created by MaveriX89 on 1/13/2025 in #support
Getting UnhandledPromiseRejection in Solid Start server function that stops dev server
That's good to know. Yeah, it's being used client side in tthe following manner:
import { useSubmission, type RouteSectionProps } from "@solidjs/router";
import { Show } from "solid-js";
import { loginOrRegister } from "~/api"; // <--- here is the import
import Logo from "../assets/logo_login.svg";
import { TextInput } from "~/components/TextInput";
import { Button } from "@kobalte/core/button";

export default function Login(props: RouteSectionProps) {
const loggingIn = useSubmission(loginOrRegister);

return (
<div class="h-full flex flex-col items-center justify-center gap-2">
<img src={Logo} width="200" />
<form action={loginOrRegister} method="post" class="flex flex-col gap-4">
<input type="hidden" name="redirectTo" value={props.params.redirectTo ?? "/"} />
<TextInput name="username" label="Username" />
<TextInput name="password" label="Password" type="password" />
<Button class="button" type="submit">
Login
</Button>
</form>
<Show when={loggingIn.result}>
<p style={{ color: "red" }} role="alert" id="error-message">
{loggingIn.result!.message}
</p>
</Show>
</div>
);
}
import { useSubmission, type RouteSectionProps } from "@solidjs/router";
import { Show } from "solid-js";
import { loginOrRegister } from "~/api"; // <--- here is the import
import Logo from "../assets/logo_login.svg";
import { TextInput } from "~/components/TextInput";
import { Button } from "@kobalte/core/button";

export default function Login(props: RouteSectionProps) {
const loggingIn = useSubmission(loginOrRegister);

return (
<div class="h-full flex flex-col items-center justify-center gap-2">
<img src={Logo} width="200" />
<form action={loginOrRegister} method="post" class="flex flex-col gap-4">
<input type="hidden" name="redirectTo" value={props.params.redirectTo ?? "/"} />
<TextInput name="username" label="Username" />
<TextInput name="password" label="Password" type="password" />
<Button class="button" type="submit">
Login
</Button>
</form>
<Show when={loggingIn.result}>
<p style={{ color: "red" }} role="alert" id="error-message">
{loggingIn.result!.message}
</p>
</Show>
</div>
);
}
33 replies
SSolidJS
Created by MaveriX89 on 1/13/2025 in #support
Getting UnhandledPromiseRejection in Solid Start server function that stops dev server
Gotcha -- so here's the breakdown with two files/modules. This was all generated from the Create Solid CLI starter (with Drizzle option checked): First one here is ./src/api/index.ts
import { action, query } from "@solidjs/router";
import { getUser as gU, logout as l, loginOrRegister as lOR } from "./server";

export const getUser = query(gU, "user");
export const loginOrRegister = action(lOR, "loginOrRegister");
export const logout = action(l, "logout");
import { action, query } from "@solidjs/router";
import { getUser as gU, logout as l, loginOrRegister as lOR } from "./server";

export const getUser = query(gU, "user");
export const loginOrRegister = action(lOR, "loginOrRegister");
export const logout = action(l, "logout");
and the second is ./src/api/server.ts
"use server"

// ...

export async function loginOrRegister(formData: FormData) {
...
}
"use server"

// ...

export async function loginOrRegister(formData: FormData) {
...
}
I believe the above aligns with what you described
33 replies
SSolidJS
Created by MaveriX89 on 1/13/2025 in #support
Getting UnhandledPromiseRejection in Solid Start server function that stops dev server
That is close to correct -- I have the use server directive at the top of the file/module.
33 replies
DTDrizzle Team
Created by MaveriX89 on 1/8/2025 in #help
drizzle-kit push not working with pgSchema
Funny enough, it came up after me going back and forth with ChatGPT haha
8 replies
DTDrizzle Team
Created by MaveriX89 on 1/8/2025 in #help
drizzle-kit push not working with pgSchema
@Optio1 I managed to find a workaround to this problem -- or maybe this is actually what is expected that we are supposed to do if we intend to make use of pgSchema in our codebases. I had to update my drizzle.config.ts to the following:
import { defineConfig } from "drizzle-kit";

export default defineConfig({
dialect: "postgresql",
schema: "./drizzle/schema/*",
out: "./drizzle/migrations/",
dbCredentials: {
url: process.env.DATABASE_URL!,
},
schemaFilter: ["public", "auth"],
});
import { defineConfig } from "drizzle-kit";

export default defineConfig({
dialect: "postgresql",
schema: "./drizzle/schema/*",
out: "./drizzle/migrations/",
dbCredentials: {
url: process.env.DATABASE_URL!,
},
schemaFilter: ["public", "auth"],
});
The key field is schemaFilter . Apparently, Drizzle Kit needs to be told what schemas it can manage in the given database. So for eveny pgSchema created, its name has to be added to that list. The default behavior is it only works on the public schema which is why drizzle-kit push was basically a no-op when I was doing it before.
8 replies
DTDrizzle Team
Created by MaveriX89 on 1/8/2025 in #help
drizzle-kit push not working with pgSchema
@Optio1 that's interesting! Thanks for looking into that. It's sad that using Postgres schemas/folders doesn't work as expected especially if we're trying to organize our tables properly.
8 replies
SSolidJS
Created by MaveriX89 on 1/7/2025 in #support
Containerized Solid Start Deployments
Ah, I made some progres and managed to successfully create a Docker image using the following:
FROM imbios/bun-node:1.1.42-22-slim

WORKDIR /app

COPY package.json bun.lock ./
RUN bun install --frozen-lockfile

COPY public ./public
COPY tsconfig.json ./
COPY app.config.ts ./
COPY drizzle ./drizzle
COPY src ./src

RUN bun run build

EXPOSE 3000

CMD ["bun", "start"]
FROM imbios/bun-node:1.1.42-22-slim

WORKDIR /app

COPY package.json bun.lock ./
RUN bun install --frozen-lockfile

COPY public ./public
COPY tsconfig.json ./
COPY app.config.ts ./
COPY drizzle ./drizzle
COPY src ./src

RUN bun run build

EXPOSE 3000

CMD ["bun", "start"]
Guess we're not really using bun as the underlying runtime because the Vinxi server uses Node if I'm not mistaken (but I'm using bun to run scripts and manage my dependencies). So I use the imbios/bun-node:1.1.42-22-slim base image (alpine did not work).
2 replies