Je Suis Un Ami
Je Suis Un Ami
Explore posts from servers
SSolidJS
Created by Je Suis Un Ami on 6/3/2024 in #support
How to Execute Server Action on Each Route Visit?
I have a home component (code in comments) In summary, what this component does is it calls a server action to check if the user is authenticated. If the user is authenticated, it redirects the user to the dashboard route. Otherwise, it redirects the user to the login route. Now, here's my question. What I want to do is perform this verification every time the home route is visited (even from a client-side redirect). From my logs however, it doesn't look like the server action is being called in subsequent visits to this route (i.e. after the account setup process is complete. The reason I know this is because "Executing checks to determine redirect" is being printed on my console. But, none of the other logs that would be printed if the action completed are. In other words authenticatedUser.result is always falsy. How would I go about doing what I am trying to do? Is there a different approach I should be taking to accomplish what I am trying to do? Thanks. Like I said, component code is in the first comment of this thread.
16 replies
SSolidJS
Created by Je Suis Un Ami on 5/2/2024 in #support
Server Actions and Cookies sending error: Cannot set headers after they are sent to the clien
Maybe I am misunderstanding something here. I am following the docs for Actions. Basically, what this component is supposed to do is check for the pressence of a session cookie. And, if the user is authenticated, redirects the client to the dashboard page. And if not, it redirects the client to the login page.
export default function Home() {
const loadAuthenticatedUser = useAction(getAuthenticatedUserAction);
const navigate = useNavigate();
loadAuthenticatedUser();
const authenticatedUser = useSubmission(getAuthenticatedUserAction);
const [_, { setUser, clearUser }] = useUserContext();
const [serverError, setServerError] = createSignal("");

createEffect(() => {
if (authenticatedUser.result) {
// If the user is authenticated, we redirect them to the dashboard page.
// otherwise, we show them the main page.
const result = authenticatedUser.result;
if (result.success) {
setUser(result.data as User);
navigate("/dashboard");
} else {
if (result.data instanceof AppException) {
setServerError(result.message);
} else {
// for now, we ust redirect them to the login page. as soon as we get more traction,
// we will have a proper home page deidicated for marketing.
clearUser();
navigate("/login");
}
}
authenticatedUser.clear();
}
});

const handleRetry = () => {
setServerError("");
authenticatedUser.retry();
};

return (
<Show
when={!serverError()}
fallback={
<ConfirmationMessage
title="Something went wrong."
description={serverError()}
buttonText="Try Again"
onClick={handleRetry}
image="img/logo.svg"
/>
}
>
<></>
</Show>
);
}
export default function Home() {
const loadAuthenticatedUser = useAction(getAuthenticatedUserAction);
const navigate = useNavigate();
loadAuthenticatedUser();
const authenticatedUser = useSubmission(getAuthenticatedUserAction);
const [_, { setUser, clearUser }] = useUserContext();
const [serverError, setServerError] = createSignal("");

createEffect(() => {
if (authenticatedUser.result) {
// If the user is authenticated, we redirect them to the dashboard page.
// otherwise, we show them the main page.
const result = authenticatedUser.result;
if (result.success) {
setUser(result.data as User);
navigate("/dashboard");
} else {
if (result.data instanceof AppException) {
setServerError(result.message);
} else {
// for now, we ust redirect them to the login page. as soon as we get more traction,
// we will have a proper home page deidicated for marketing.
clearUser();
navigate("/login");
}
}
authenticatedUser.clear();
}
});

const handleRetry = () => {
setServerError("");
authenticatedUser.retry();
};

return (
<Show
when={!serverError()}
fallback={
<ConfirmationMessage
title="Something went wrong."
description={serverError()}
buttonText="Try Again"
onClick={handleRetry}
image="img/logo.svg"
/>
}
>
<></>
</Show>
);
}
I included the action definition in the comments.
29 replies
SSolidJS
Created by Je Suis Un Ami on 4/23/2024 in #support
Hydration Mismatch Error Every Time I Update a Component
No description
3 replies
SSolidJS
Created by Je Suis Un Ami on 3/17/2024 in #support
Dynamic Route Being Called Twice
No description
2 replies
SIASapphire - Imagine a framework
Created by Je Suis Un Ami on 3/11/2024 in #sapphire-support
Formatted Logs
Is there a way to extend the existing logger within Sapphire? I saw that in the logger argument of the client constructor I can pass an instance of ILogger. So, I thought I could just extend the Logger class from @sapphire/framework and pass that to the instance argument. Doesn’t seem to work. It’s not formatting my logs. Seems to stick to the default logger. Are there any other options? I am kind of looking for a way to just work with the existing logger instead of creating an entirely new plugin. The only real change I am making is formatting log messages like so: [context]: message, where context shows where the log is coming from (I.e. MyCommand.chatInputRun`. And message is the normal log message. I could just pass a formatting function to the current logger. But this is a very error-prone solution. Thanks in advance.
16 replies
SIASapphire - Imagine a framework
Created by Je Suis Un Ami on 3/5/2024 in #sapphire-support
Failure Handling With Listeners.
This is more a design/architecture question. Just need more input. So, a few of the commands I am writing for my bot are getting… complicated. By that I mean, database state is being updated, which leads to server categories being updated, and channels being updated, etc…So, instead of putting all the logic in my command class, I decided to go the event emitter route and this.container.client.emit() route and move the server channel/category/role updating to a listener that just responds to the custom event I emitted. Something that crosses my mind though is how to handle if one of the listeners fail for whatever reason. Does Sapphire provide an option to automatically retry listeners if they fail? Or am I gonna need to manually handle that somehow?
15 replies
SIASapphire - Imagine a framework
Created by Je Suis Un Ami on 3/3/2024 in #sapphire-support
Running Async Code in Precinditions
I didn’t see this in the docs. But, is it possible to run async code in preconditions? TLDR: I need to load a “guild configuration” from my database, which contains the ID of a role that the caller must (in the server) to be allowed to execute some command. Long question is, users (server owners) of my bot must run a “setup” command, which will create a “GuildProfile” for their server before they are allowed to use any of the other commands. In my precondition, what I want to do is get the “GuildProfile” for the server and see if the caller of the command has the role specified in that profile. If so, return this.ok(). Otherwise, return this.error(). However, it doesn’t look like I can run async code in preconditions. So, is there a way to do so? Or am I gonna need to perform this check in the *Run() method of my command?
4 replies
SIASapphire - Imagine a framework
Created by Je Suis Un Ami on 3/2/2024 in #sapphire-support
Getting Data from .env File
I created a new Sapphire app using the CLI. I am using swc. And, I want to ask how do access env variables in my bot? The project contains a src/.env file . So, naturally, I thought to put my discord token there and access it in my src/index.ts file as follows.
const main = async () => {
try {
client.logger.info('Logging in');
await client.login(process.env.DISCORD_TOKEN);
client.logger.info('logged in');
} catch (error) {
client.logger.fatal(error);
await client.destroy();
process.exit(1);
}
};
const main = async () => {
try {
client.logger.info('Logging in');
await client.login(process.env.DISCORD_TOKEN);
client.logger.info('logged in');
} catch (error) {
client.logger.fatal(error);
await client.destroy();
process.exit(1);
}
};
However, running this throws an error : Error [TokenInvalid]: An invalid token was provided.. However, it runs if I pass the discord token as a string literal to the client.login() method. So, this tells me the src/.env file isn't getting included in the compiled source code. And, upon reviewing the outputted 'dist folder, it appears this is the case. How would I fix this? Or, is there a different way I am supposed to access environment variables?
128 replies
SSolidJS
Created by Je Suis Un Ami on 8/30/2023 in #support
Context Not Being Defined
I am running into a problem where the AuthContext isn't being defined in m app. Here's my App component:
const App: Component = () => {
console.log("Rendering App Component");
return (
<MetaProvider>
<Title>{siteName}</Title>
<AuthProvider>
<Main />
</AuthProvider>
</MetaProvider>
);
};
const App: Component = () => {
console.log("Rendering App Component");
return (
<MetaProvider>
<Title>{siteName}</Title>
<AuthProvider>
<Main />
</AuthProvider>
</MetaProvider>
);
};
For convenience, here is my <mAIN /> component:
const Main: Component = () => {
console.log("Rendering main");
const [_, authenticated] = useAuthContext();
console.log(`Authenticated: ${authenticated()}`);
const Content = useRoutes(routes);
return (
<Router>
<div class="h-full bg-white">
<Show
when={authenticated()}
fallback={
<DefaultLayout>
<Content />
</DefaultLayout>
}
>
<ProfileProvider>
<EnsureClientSetup>
<AppProvider>
<DashboardLayout>
<Content />
</DashboardLayout>
</AppProvider>
</EnsureClientSetup>
</ProfileProvider>
</Show>
</div>
</Router>
);
};
const Main: Component = () => {
console.log("Rendering main");
const [_, authenticated] = useAuthContext();
console.log(`Authenticated: ${authenticated()}`);
const Content = useRoutes(routes);
return (
<Router>
<div class="h-full bg-white">
<Show
when={authenticated()}
fallback={
<DefaultLayout>
<Content />
</DefaultLayout>
}
>
<ProfileProvider>
<EnsureClientSetup>
<AppProvider>
<DashboardLayout>
<Content />
</DashboardLayout>
</AppProvider>
</EnsureClientSetup>
</ProfileProvider>
</Show>
</div>
</Router>
);
};
Essentially, the error being thrown is Uncaught TypeError: Cannot read properties of null, referring to the auth check being done by the authenticated() signal, defined in the AuthContext context. Here is the slimmed down version of my AuthContext:
export const AuthProvider: ParentComponent = (props) => {
console.log("Defining Auth Provider");
// ... more code here

<ErrorBoundary
fallback={(error: Error) => (
<DefaultLayout>
<span>
<AppError error={error} onRetry={refresh} />
</span>
</DefaultLayout>
)}
>
<Suspense>
<AuthContext.Provider
value={[
auth,
isAuthenticated,
{
authenticate: authenticate,
refreshAuth: refresh,
unauthenticate: unauthenticate,
},
]}
>
{props.children}
</AuthContext.Provider>
</Suspense>
</ErrorBoundary>
);
}

export const useAuthContext = () => {
return useContext(AuthContext)!;
};
export const AuthProvider: ParentComponent = (props) => {
console.log("Defining Auth Provider");
// ... more code here

<ErrorBoundary
fallback={(error: Error) => (
<DefaultLayout>
<span>
<AppError error={error} onRetry={refresh} />
</span>
</DefaultLayout>
)}
>
<Suspense>
<AuthContext.Provider
value={[
auth,
isAuthenticated,
{
authenticate: authenticate,
refreshAuth: refresh,
unauthenticate: unauthenticate,
},
]}
>
{props.children}
</AuthContext.Provider>
</Suspense>
</ErrorBoundary>
);
}

export const useAuthContext = () => {
return useContext(AuthContext)!;
};
In my logs, I know that AuthContext is not being defined because the print statement defined in it is never shown. How would I fix this?
2 replies
SSolidJS
Created by Je Suis Un Ami on 6/11/2023 in #support
Saving Results of routeData() into a Context
What is the proper way to save the results of routeData() into a context? So, here's my setup. Here's my root.
<Body class="bg-primary h-min w-screen">
<div class="text-center mx-auto text-spring pt-4 px-0 w-full">
<Suspense>
<ErrorBoundary>
<Navigation />
<IslandsProvider>
<Routes>
<FileRoutes />
</Routes>
</IslandsProvider>
<Footer />
</ErrorBoundary>
</Suspense>
<Scripts />
</div>
</Body>
<Body class="bg-primary h-min w-screen">
<div class="text-center mx-auto text-spring pt-4 px-0 w-full">
<Suspense>
<ErrorBoundary>
<Navigation />
<IslandsProvider>
<Routes>
<FileRoutes />
</Routes>
</IslandsProvider>
<Footer />
</ErrorBoundary>
</Suspense>
<Scripts />
</div>
</Body>
And, in my route component, I have it like this:
export function routeData() {
const resource = createRouteData(async () => await getLatestIslands());
console.log(resource());
return resource;
}

export default function Home() {
console.log("Defining index");
const islands = useRouteData<typeof routeData>();
console.log(islands());
const [_, addIslands] = useIslandsContext();
addIslands(islands()!);

return (
<main>
<FeaturedIsland />
<LatestIslands />
</main>
);
}
export function routeData() {
const resource = createRouteData(async () => await getLatestIslands());
console.log(resource());
return resource;
}

export default function Home() {
console.log("Defining index");
const islands = useRouteData<typeof routeData>();
console.log(islands());
const [_, addIslands] = useIslandsContext();
addIslands(islands()!);

return (
<main>
<FeaturedIsland />
<LatestIslands />
</main>
);
}
According to my logs, data is present in both the routeData() and when the component initially renders. However, it doesn't seem like it is ever put into the context (as in, it's saying it is undefined on my UI). How would I go about this?
2 replies
SSolidJS
Created by Je Suis Un Ami on 5/4/2023 in #support
props.children is not defined.
I have this component.
const AuthProvider: Component<AuthContextProps> = (props) => {
/// the local store.
const [tokenStorage, setTokenStorage] = createLocalStorage({
api: localStorage,
prefix: "vista-auth-",
deserializer: (data) => {
if (!data || data == "undefined") {
return "";
}
return data;
},
serializer: (value, key, options) => {
return value;
},
});
const [auth, setAuth] = createStore({
access: tokenStorage.access,
refresh: tokenStorage.refresh,
get authenticated(): boolean {
const hasAccess = this.access.length > 0;
const hasRefresh = this.refresh.length > 0;
return hasAccess || hasRefresh;
},
} as AuthState);

return (
<AuthContext.Provider value={auth}>
{props.children!}
</AuthContext.Provider>
);
};
const AuthProvider: Component<AuthContextProps> = (props) => {
/// the local store.
const [tokenStorage, setTokenStorage] = createLocalStorage({
api: localStorage,
prefix: "vista-auth-",
deserializer: (data) => {
if (!data || data == "undefined") {
return "";
}
return data;
},
serializer: (value, key, options) => {
return value;
},
});
const [auth, setAuth] = createStore({
access: tokenStorage.access,
refresh: tokenStorage.refresh,
get authenticated(): boolean {
const hasAccess = this.access.length > 0;
const hasRefresh = this.refresh.length > 0;
return hasAccess || hasRefresh;
},
} as AuthState);

return (
<AuthContext.Provider value={auth}>
{props.children!}
</AuthContext.Provider>
);
};
My IDE is telling me that props.children isn't defined somehow. I'm guessing this is just some typing problem? How would I fix this?
8 replies
SSolidJS
Created by Je Suis Un Ami on 4/22/2023 in #support
Creating an Observable from a store.
Is there a way I can create an observable from a store? Essentially, what I want to do this:
import { observable } from “solid-js”;
import { createStore } from “solid-js/store”;
import { tap, map } from “RxJS/operators”;
import {from } from “RxJS”;

Interface AuthTokens {
access: string;
refresh: string;
}

const [tokens, setTokens] = createStore<AuthTokens>({});

const tokens$ = observable(tokens).pipe(
tap(value => //save to storage),
map(tokens => {
return from(fetch(…)).pipe(…)
})
)
import { observable } from “solid-js”;
import { createStore } from “solid-js/store”;
import { tap, map } from “RxJS/operators”;
import {from } from “RxJS”;

Interface AuthTokens {
access: string;
refresh: string;
}

const [tokens, setTokens] = createStore<AuthTokens>({});

const tokens$ = observable(tokens).pipe(
tap(value => //save to storage),
map(tokens => {
return from(fetch(…)).pipe(…)
})
)
Or, something like that at least. This fails because the observable() function accepts an Accessor, which pretty much is only signals. Is there a way I can make it work with stores as well?
4 replies