feat: migrate auth from supabase to better auth (#596)

* feat: add README for @cio/db package and remove existingAccounts.json

* load session, load profile and organization, add create profile hook

* chore: cache session request

The trick was passing all the cookies to the backend. Previously I was only passing the better-auth.session_token and not better-auth.session_data. Read about the difference here https://www.better-auth.com/docs/concepts/cookies#custom-cookies

* feat: login, logout, onboarding, verify email, reset password.

* feat: complete change email and email verification

* feat: standardise how we make rpc calls and create org endpoints

* fix ui errors

* fix: handle potential undefined customerId and standardize avatar URL property

* refactor: standardize custom domain handling and update telegram chat ID references

* chore: add tailwind prefix to @cio/ui

this fixed the media query issues because  @cio/ui classes were overriding this dashboard tailwind build

* chore: clean up org sidebar

* chore: persist mode state

* feat: implement order breadcrumbs

* chore: upgrade to better auth 1.4

* chore: address common auth flow bugs and setup app for others to setup locally.
This commit is contained in:
Rotimi Best
2025-11-24 01:00:50 +01:00
committed by GitHub
parent 24741644d6
commit a3924100dd
567 changed files with 22364 additions and 13437 deletions
+34
View File
@@ -0,0 +1,34 @@
import Root from "./item.svelte";
import Group from "./item-group.svelte";
import Separator from "./item-separator.svelte";
import Header from "./item-header.svelte";
import Footer from "./item-footer.svelte";
import Content from "./item-content.svelte";
import Title from "./item-title.svelte";
import Description from "./item-description.svelte";
import Actions from "./item-actions.svelte";
import Media from "./item-media.svelte";
export {
Root,
Group,
Separator,
Header,
Footer,
Content,
Title,
Description,
Actions,
Media,
//
Root as Item,
Group as ItemGroup,
Separator as ItemSeparator,
Header as ItemHeader,
Footer as ItemFooter,
Content as ItemContent,
Title as ItemTitle,
Description as ItemDescription,
Actions as ItemActions,
Media as ItemMedia,
};
@@ -0,0 +1,15 @@
<script lang="ts">
import { cn, type WithElementRef } from '../../tools';
import type { HTMLAttributes } from 'svelte/elements';
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div bind:this={ref} data-slot="item-actions" class={cn('ui:flex ui:items-center ui:gap-2', className)} {...restProps}>
{@render children?.()}
</div>
@@ -0,0 +1,20 @@
<script lang="ts">
import { cn, type WithElementRef } from '../../tools';
import type { HTMLAttributes } from 'svelte/elements';
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
data-slot="item-content"
class={cn('ui:flex ui:flex-1 ui:flex-col ui:gap-1 ui:[&+[data-slot=item-content]]:flex-none', className)}
{...restProps}
>
{@render children?.()}
</div>
@@ -0,0 +1,24 @@
<script lang="ts">
import { cn, type WithElementRef } from '../../tools';
import type { HTMLAttributes } from 'svelte/elements';
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLParagraphElement>> = $props();
</script>
<p
bind:this={ref}
data-slot="item-description"
class={cn(
'ui:text-muted-foreground ui:line-clamp-2 ui:text-balance ui:text-sm ui:font-normal ui:leading-normal',
'ui:[&>a:hover]:text-primary ui:[&>a]:underline ui:[&>a]:underline-offset-4',
className
)}
{...restProps}
>
{@render children?.()}
</p>
@@ -0,0 +1,20 @@
<script lang="ts">
import { cn, type WithElementRef } from '../../tools';
import type { HTMLAttributes } from 'svelte/elements';
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
data-slot="item-footer"
class={cn('ui:flex ui:basis-full ui:items-center ui:justify-between ui:gap-2', className)}
{...restProps}
>
{@render children?.()}
</div>
@@ -0,0 +1,21 @@
<script lang="ts">
import { cn, type WithElementRef } from '../../tools';
import type { HTMLAttributes } from 'svelte/elements';
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
role="list"
data-slot="item-group"
class={cn('ui:group/item-group ui:flex ui:flex-col', className)}
{...restProps}
>
{@render children?.()}
</div>
@@ -0,0 +1,20 @@
<script lang="ts">
import { cn, type WithElementRef } from '../../tools';
import type { HTMLAttributes } from 'svelte/elements';
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
data-slot="item-header"
class={cn('ui:flex ui:basis-full ui:items-center ui:justify-between ui:gap-2', className)}
{...restProps}
>
{@render children?.()}
</div>
@@ -0,0 +1,42 @@
<script lang="ts" module>
import { tv, type VariantProps } from 'tailwind-variants';
export const itemMediaVariants = tv({
base: 'ui:flex ui:shrink-0 ui:items-center ui:justify-center ui:gap-2 ui:group-has-[[data-slot=item-description]]/item:translate-y-0.5 ui:group-has-[[data-slot=item-description]]/item:self-start ui:[&_svg]:pointer-events-none',
variants: {
variant: {
default: 'ui:bg-transparent',
icon: "ui:bg-muted ui:size-8 ui:rounded-sm ui:border ui:[&_svg:not([class*='size-'])]:size-4",
image: 'ui:size-10 ui:overflow-hidden ui:rounded-sm ui:[&_img]:size-full ui:[&_img]:object-cover'
}
},
defaultVariants: {
variant: 'default'
}
});
export type ItemMediaVariant = VariantProps<typeof itemMediaVariants>['variant'];
</script>
<script lang="ts">
import { cn, type WithElementRef } from '../../tools';
import type { HTMLAttributes } from 'svelte/elements';
let {
ref = $bindable(null),
class: className,
children,
variant = 'default',
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & { variant?: ItemMediaVariant } = $props();
</script>
<div
bind:this={ref}
data-slot="item-media"
data-variant={variant}
class={cn(itemMediaVariants({ variant }), className)}
{...restProps}
>
{@render children?.()}
</div>
@@ -0,0 +1,15 @@
<script lang="ts">
import { Separator } from '../separator';
import { cn } from '../../tools';
import type { ComponentProps } from 'svelte';
let { ref = $bindable(null), class: className, ...restProps }: ComponentProps<typeof Separator> = $props();
</script>
<Separator
bind:ref
data-slot="item-separator"
orientation="horizontal"
class={cn('ui:my-0', className)}
{...restProps}
/>
@@ -0,0 +1,20 @@
<script lang="ts">
import { cn, type WithElementRef } from '../../tools';
import type { HTMLAttributes } from 'svelte/elements';
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
data-slot="item-title"
class={cn('ui:flex ui:w-fit ui:items-center ui:gap-2 ui:text-sm ui:font-medium ui:leading-snug', className)}
{...restProps}
>
{@render children?.()}
</div>
+60
View File
@@ -0,0 +1,60 @@
<script lang="ts" module>
import { tv, type VariantProps } from 'tailwind-variants';
export const itemVariants = tv({
base: 'group/item ui:[a]:hover:bg-accent/50 ui:[a]:transition-colors ui:focus-visible:border-ring ui:focus-visible:ring-ring/50 ui:flex ui:flex-wrap ui:items-center ui:rounded-md ui:border ui:border-transparent ui:text-sm ui:outline-none ui:transition-colors ui:duration-100 ui:focus-visible:ring-[3px]',
variants: {
variant: {
default: 'ui:bg-transparent',
outline: 'ui:border-border',
muted: 'ui:bg-muted/50'
},
size: {
default: 'ui:gap-4 ui:p-4',
sm: 'ui:gap-2.5 ui:px-4 ui:py-3'
}
},
defaultVariants: {
variant: 'default',
size: 'default'
}
});
export type ItemSize = VariantProps<typeof itemVariants>['size'];
export type ItemVariant = VariantProps<typeof itemVariants>['variant'];
</script>
<script lang="ts">
import { cn, type WithElementRef } from '../../tools';
import type { HTMLAttributes } from 'svelte/elements';
import type { Snippet } from 'svelte';
let {
ref = $bindable(null),
class: className,
child,
variant,
size,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
child?: Snippet<[{ props: Record<string, unknown> }]>;
variant?: ItemVariant;
size?: ItemSize;
} = $props();
const mergedProps = $derived({
class: cn(itemVariants({ variant, size }), className),
'data-slot': 'item',
'data-variant': variant,
'data-size': size,
...restProps
});
</script>
{#if child}
{@render child({ props: mergedProps })}
{:else}
<div bind:this={ref} {...mergedProps}>
{@render mergedProps.children?.()}
</div>
{/if}