ConnectRPC: Initialize buf workspace, generate ts files, use using connect-query
Some checks failed
Build and Push Docker Image / build (push) Failing after 4m20s

This commit is contained in:
2026-06-03 13:24:17 +02:00
parent 30a52c800a
commit 5519c016aa
16 changed files with 6382 additions and 402 deletions

18
buf.gen.yaml Normal file
View File

@@ -0,0 +1,18 @@
version: v2
plugins:
- remote: buf.build/bufbuild/es:v2.12.0
out: src/gen
opt: target=ts
include_imports: true
- remote: buf.build/connectrpc/query-es:v2.2.0
out: src/gen
opt:
- target=ts
managed:
enabled: true
override:
- file_option: go_package_prefix
value: git.kocoder.xyz/vt/shortener/internal
disable:
- file_option: go_package
module: buf.build/bufbuild/protovalidate

6
buf.lock Normal file
View File

@@ -0,0 +1,6 @@
# Generated by buf. DO NOT EDIT.
version: v2
deps:
- name: buf.build/bufbuild/protovalidate
commit: 50325440f8f24053b047484a6bf60b76
digest: b5:74cb6f5c0853c3c10aafc701614194bbd63326bdb8ef4068214454b8894b03ba4113e04b3a33a8321cdf05336e37db4dc14a5e2495db8462566914f36086ba31

9
buf.yaml Normal file
View File

@@ -0,0 +1,9 @@
version: v2
deps:
- buf.build/bufbuild/protovalidate
lint:
use:
- STANDARD
breaking:
use:
- FILE

View File

@@ -13,6 +13,11 @@
"check": "biome check"
},
"dependencies": {
"@bufbuild/protobuf": "^2.12.0",
"@bufbuild/protovalidate": "^1.2.0",
"@connectrpc/connect": "^2.1.1",
"@connectrpc/connect-query": "^2.2.0",
"@connectrpc/connect-web": "^2.1.1",
"@fontsource-variable/noto-sans": "^5.2.10",
"@fontsource/inter": "^5.1.1",
"@kobalte/core": "^0.13.11",
@@ -46,6 +51,7 @@
},
"devDependencies": {
"@biomejs/biome": "2.4.5",
"@bufbuild/buf": "^1.70.0",
"@solidjs/testing-library": "^0.8.10",
"@tanstack/devtools-vite": "latest",
"jsdom": "^28.1.0",

1281
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,7 @@
allowBuilds:
'@bufbuild/buf': true
esbuild: set this to true or false
msw: true
onlyBuiltDependencies:
- esbuild
- lightningcss
- lightningcss

View File

@@ -1,13 +1,14 @@
import { Link } from '@tanstack/solid-router'
import { Link } from "@tanstack/solid-router";
import TanStackQueryHeaderUser from '../integrations/tanstack-query/header-user.tsx'
import TanStackQueryHeaderUser from "../integrations/tanstack-query/header-user.tsx";
export default function Header() {
return (
<div class="flex items-center justify-between px-4">
<Link to="/">Home</Link>
<Link to="/todo">Todo</Link>
<Link to="/shorten">Shorten</Link>
<TanStackQueryHeaderUser />
</div>
)
);
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,28 @@
// @generated by protoc-gen-connect-query v2.2.0 with parameter "target=ts"
// @generated from file proto/shorten/v1/shorten.proto (package proto.shorten.v1, syntax proto3)
/* eslint-disable */
import { ShortenService } from "./shorten_pb";
/**
* @generated from rpc proto.shorten.v1.ShortenService.CreateURLRedirection
*/
export const createURLRedirection = ShortenService.method.createURLRedirection;
/**
* @generated from rpc proto.shorten.v1.ShortenService.ListURLRedirections
*/
export const listURLRedirections = ShortenService.method.listURLRedirections;
/**
* rpc GetURLRedirection(GetURLRedirectionRequest) returns
* (GetURLRedirectionResponse) {}
*
* @generated from rpc proto.shorten.v1.ShortenService.DeactivateURLRedirection
*/
export const deactivateURLRedirection = ShortenService.method.deactivateURLRedirection;
/**
* @generated from rpc proto.shorten.v1.ShortenService.DeleteURLRedirection
*/
export const deleteURLRedirection = ShortenService.method.deleteURLRedirection;

View File

@@ -0,0 +1,248 @@
// @generated by protoc-gen-es v2.12.0 with parameter "target=ts"
// @generated from file proto/shorten/v1/shorten.proto (package proto.shorten.v1, syntax proto3)
/* eslint-disable */
import type { GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv2";
import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2";
import { file_buf_validate_validate } from "../../../buf/validate/validate_pb";
import type { Timestamp } from "@bufbuild/protobuf/wkt";
import { file_google_protobuf_timestamp } from "@bufbuild/protobuf/wkt";
import type { Message } from "@bufbuild/protobuf";
/**
* Describes the file proto/shorten/v1/shorten.proto.
*/
export const file_proto_shorten_v1_shorten: GenFile = /*@__PURE__*/
fileDesc("Ch5wcm90by9zaG9ydGVuL3YxL3Nob3J0ZW4ucHJvdG8SEHByb3RvLnNob3J0ZW4udjEiUgobQ3JlYXRlVVJMUmVkaXJlY3Rpb25SZXF1ZXN0EhwKCnNob3J0X2NvZGUYASABKAlCCLpIBXIDmAEKEhUKA3VybBgCIAEoCUIIukgFcgOIAQEiKgocQ3JlYXRlVVJMUmVkaXJlY3Rpb25SZXNwb25zZRIKCgJvaxgBIAEoCCLQAQoOVVJMUmVkaXJlY3Rpb24SDgoGdXJsX2lkGAEgASgFEhIKCnNob3J0X2NvZGUYAyABKAkSCwoDdXJsGAIgASgJEi4KCmNyZWF0ZWRfYXQYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEi4KCmV4cGlyZXNfYXQYBSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhEKCWlzX2FjdGl2ZRgGIAEoCBIaChJjbGlja19jb3VudF9ieV9kYXkYByADKAUiHAoaTGlzdFVSTFJlZGlyZWN0aW9uc1JlcXVlc3QiWQobTGlzdFVSTFJlZGlyZWN0aW9uc1Jlc3BvbnNlEjoKEHVybF9yZWRpcmVjdGlvbnMYASADKAsyIC5wcm90by5zaG9ydGVuLnYxLlVSTFJlZGlyZWN0aW9uIkQKH0RlYWN0aXZhdGVVUkxSZWRpcmVjdGlvblJlcXVlc3QSDgoGdXJsX2lkGAEgASgFEhEKCWlzX2FjdGl2ZRgCIAEoCCIuCiBEZWFjdGl2YXRlVVJMUmVkaXJlY3Rpb25SZXNwb25zZRIKCgJvaxgBIAEoCCItChtEZWxldGVVUkxSZWRpcmVjdGlvblJlcXVlc3QSDgoGdXJsX2lkGAEgASgFIioKHERlbGV0ZVVSTFJlZGlyZWN0aW9uUmVzcG9uc2USCgoCb2sYASABKAgy/gMKDlNob3J0ZW5TZXJ2aWNlEncKFENyZWF0ZVVSTFJlZGlyZWN0aW9uEi0ucHJvdG8uc2hvcnRlbi52MS5DcmVhdGVVUkxSZWRpcmVjdGlvblJlcXVlc3QaLi5wcm90by5zaG9ydGVuLnYxLkNyZWF0ZVVSTFJlZGlyZWN0aW9uUmVzcG9uc2UiABJ0ChNMaXN0VVJMUmVkaXJlY3Rpb25zEiwucHJvdG8uc2hvcnRlbi52MS5MaXN0VVJMUmVkaXJlY3Rpb25zUmVxdWVzdBotLnByb3RvLnNob3J0ZW4udjEuTGlzdFVSTFJlZGlyZWN0aW9uc1Jlc3BvbnNlIgASgwEKGERlYWN0aXZhdGVVUkxSZWRpcmVjdGlvbhIxLnByb3RvLnNob3J0ZW4udjEuRGVhY3RpdmF0ZVVSTFJlZGlyZWN0aW9uUmVxdWVzdBoyLnByb3RvLnNob3J0ZW4udjEuRGVhY3RpdmF0ZVVSTFJlZGlyZWN0aW9uUmVzcG9uc2UiABJ3ChREZWxldGVVUkxSZWRpcmVjdGlvbhItLnByb3RvLnNob3J0ZW4udjEuRGVsZXRlVVJMUmVkaXJlY3Rpb25SZXF1ZXN0Gi4ucHJvdG8uc2hvcnRlbi52MS5EZWxldGVVUkxSZWRpcmVjdGlvblJlc3BvbnNlIgBCyAEKFGNvbS5wcm90by5zaG9ydGVuLnYxQgxTaG9ydGVuUHJvdG9QAVpAZ2l0LmtvY29kZXIueHl6L3Z0L3Nob3J0ZW5lci9pbnRlcm5hbC9wcm90by9zaG9ydGVuL3YxO3Nob3J0ZW52MaICA1BTWKoCEFByb3RvLlNob3J0ZW4uVjHKAhBQcm90b1xTaG9ydGVuXFYx4gIcUHJvdG9cU2hvcnRlblxWMVxHUEJNZXRhZGF0YeoCElByb3RvOjpTaG9ydGVuOjpWMWIGcHJvdG8z", [file_buf_validate_validate, file_google_protobuf_timestamp]);
/**
* @generated from message proto.shorten.v1.CreateURLRedirectionRequest
*/
export type CreateURLRedirectionRequest = Message<"proto.shorten.v1.CreateURLRedirectionRequest"> & {
/**
* @generated from field: string short_code = 1;
*/
shortCode: string;
/**
* @generated from field: string url = 2;
*/
url: string;
};
/**
* Describes the message proto.shorten.v1.CreateURLRedirectionRequest.
* Use `create(CreateURLRedirectionRequestSchema)` to create a new message.
*/
export const CreateURLRedirectionRequestSchema: GenMessage<CreateURLRedirectionRequest> = /*@__PURE__*/
messageDesc(file_proto_shorten_v1_shorten, 0);
/**
* @generated from message proto.shorten.v1.CreateURLRedirectionResponse
*/
export type CreateURLRedirectionResponse = Message<"proto.shorten.v1.CreateURLRedirectionResponse"> & {
/**
* @generated from field: bool ok = 1;
*/
ok: boolean;
};
/**
* Describes the message proto.shorten.v1.CreateURLRedirectionResponse.
* Use `create(CreateURLRedirectionResponseSchema)` to create a new message.
*/
export const CreateURLRedirectionResponseSchema: GenMessage<CreateURLRedirectionResponse> = /*@__PURE__*/
messageDesc(file_proto_shorten_v1_shorten, 1);
/**
* @generated from message proto.shorten.v1.URLRedirection
*/
export type URLRedirection = Message<"proto.shorten.v1.URLRedirection"> & {
/**
* @generated from field: int32 url_id = 1;
*/
urlId: number;
/**
* @generated from field: string short_code = 3;
*/
shortCode: string;
/**
* @generated from field: string url = 2;
*/
url: string;
/**
* @generated from field: google.protobuf.Timestamp created_at = 4;
*/
createdAt?: Timestamp | undefined;
/**
* @generated from field: google.protobuf.Timestamp expires_at = 5;
*/
expiresAt?: Timestamp | undefined;
/**
* @generated from field: bool is_active = 6;
*/
isActive: boolean;
/**
* @generated from field: repeated int32 click_count_by_day = 7;
*/
clickCountByDay: number[];
};
/**
* Describes the message proto.shorten.v1.URLRedirection.
* Use `create(URLRedirectionSchema)` to create a new message.
*/
export const URLRedirectionSchema: GenMessage<URLRedirection> = /*@__PURE__*/
messageDesc(file_proto_shorten_v1_shorten, 2);
/**
* @generated from message proto.shorten.v1.ListURLRedirectionsRequest
*/
export type ListURLRedirectionsRequest = Message<"proto.shorten.v1.ListURLRedirectionsRequest"> & {
};
/**
* Describes the message proto.shorten.v1.ListURLRedirectionsRequest.
* Use `create(ListURLRedirectionsRequestSchema)` to create a new message.
*/
export const ListURLRedirectionsRequestSchema: GenMessage<ListURLRedirectionsRequest> = /*@__PURE__*/
messageDesc(file_proto_shorten_v1_shorten, 3);
/**
* @generated from message proto.shorten.v1.ListURLRedirectionsResponse
*/
export type ListURLRedirectionsResponse = Message<"proto.shorten.v1.ListURLRedirectionsResponse"> & {
/**
* @generated from field: repeated proto.shorten.v1.URLRedirection url_redirections = 1;
*/
urlRedirections: URLRedirection[];
};
/**
* Describes the message proto.shorten.v1.ListURLRedirectionsResponse.
* Use `create(ListURLRedirectionsResponseSchema)` to create a new message.
*/
export const ListURLRedirectionsResponseSchema: GenMessage<ListURLRedirectionsResponse> = /*@__PURE__*/
messageDesc(file_proto_shorten_v1_shorten, 4);
/**
* @generated from message proto.shorten.v1.DeactivateURLRedirectionRequest
*/
export type DeactivateURLRedirectionRequest = Message<"proto.shorten.v1.DeactivateURLRedirectionRequest"> & {
/**
* @generated from field: int32 url_id = 1;
*/
urlId: number;
/**
* @generated from field: bool is_active = 2;
*/
isActive: boolean;
};
/**
* Describes the message proto.shorten.v1.DeactivateURLRedirectionRequest.
* Use `create(DeactivateURLRedirectionRequestSchema)` to create a new message.
*/
export const DeactivateURLRedirectionRequestSchema: GenMessage<DeactivateURLRedirectionRequest> = /*@__PURE__*/
messageDesc(file_proto_shorten_v1_shorten, 5);
/**
* @generated from message proto.shorten.v1.DeactivateURLRedirectionResponse
*/
export type DeactivateURLRedirectionResponse = Message<"proto.shorten.v1.DeactivateURLRedirectionResponse"> & {
/**
* @generated from field: bool ok = 1;
*/
ok: boolean;
};
/**
* Describes the message proto.shorten.v1.DeactivateURLRedirectionResponse.
* Use `create(DeactivateURLRedirectionResponseSchema)` to create a new message.
*/
export const DeactivateURLRedirectionResponseSchema: GenMessage<DeactivateURLRedirectionResponse> = /*@__PURE__*/
messageDesc(file_proto_shorten_v1_shorten, 6);
/**
* @generated from message proto.shorten.v1.DeleteURLRedirectionRequest
*/
export type DeleteURLRedirectionRequest = Message<"proto.shorten.v1.DeleteURLRedirectionRequest"> & {
/**
* @generated from field: int32 url_id = 1;
*/
urlId: number;
};
/**
* Describes the message proto.shorten.v1.DeleteURLRedirectionRequest.
* Use `create(DeleteURLRedirectionRequestSchema)` to create a new message.
*/
export const DeleteURLRedirectionRequestSchema: GenMessage<DeleteURLRedirectionRequest> = /*@__PURE__*/
messageDesc(file_proto_shorten_v1_shorten, 7);
/**
* @generated from message proto.shorten.v1.DeleteURLRedirectionResponse
*/
export type DeleteURLRedirectionResponse = Message<"proto.shorten.v1.DeleteURLRedirectionResponse"> & {
/**
* @generated from field: bool ok = 1;
*/
ok: boolean;
};
/**
* Describes the message proto.shorten.v1.DeleteURLRedirectionResponse.
* Use `create(DeleteURLRedirectionResponseSchema)` to create a new message.
*/
export const DeleteURLRedirectionResponseSchema: GenMessage<DeleteURLRedirectionResponse> = /*@__PURE__*/
messageDesc(file_proto_shorten_v1_shorten, 8);
/**
* @generated from service proto.shorten.v1.ShortenService
*/
export const ShortenService: GenService<{
/**
* @generated from rpc proto.shorten.v1.ShortenService.CreateURLRedirection
*/
createURLRedirection: {
methodKind: "unary";
input: typeof CreateURLRedirectionRequestSchema;
output: typeof CreateURLRedirectionResponseSchema;
},
/**
* @generated from rpc proto.shorten.v1.ShortenService.ListURLRedirections
*/
listURLRedirections: {
methodKind: "unary";
input: typeof ListURLRedirectionsRequestSchema;
output: typeof ListURLRedirectionsResponseSchema;
},
/**
* rpc GetURLRedirection(GetURLRedirectionRequest) returns
* (GetURLRedirectionResponse) {}
*
* @generated from rpc proto.shorten.v1.ShortenService.DeactivateURLRedirection
*/
deactivateURLRedirection: {
methodKind: "unary";
input: typeof DeactivateURLRedirectionRequestSchema;
output: typeof DeactivateURLRedirectionResponseSchema;
},
/**
* @generated from rpc proto.shorten.v1.ShortenService.DeleteURLRedirection
*/
deleteURLRedirection: {
methodKind: "unary";
input: typeof DeleteURLRedirectionRequestSchema;
output: typeof DeleteURLRedirectionResponseSchema;
},
}> = /*@__PURE__*/
serviceDesc(file_proto_shorten_v1_shorten, 0);

View File

@@ -0,0 +1,54 @@
import { createContext, useContext } from "solid-js";
import type { JSX } from "solid-js";
import type { Transport, ConnectError } from "@connectrpc/connect";
import { createQuery } from "@tanstack/solid-query";
import type { CreateQueryResult, CreateQueryOptions } from "@tanstack/solid-query";
import { createQueryOptions } from "@connectrpc/connect-query";
import type { DescMethodUnary, DescMessage, MessageInitShape, MessageShape } from "@bufbuild/protobuf";
const TransportContext = createContext<Transport>();
export interface TransportProviderProps {
transport: Transport;
children: JSX.Element;
}
export function TransportProvider(props: TransportProviderProps) {
console.log("TransportProvider rendering, transport:", props.transport);
return (
<TransportContext.Provider value={props.transport}>
{props.children}
</TransportContext.Provider>
);
}
export function useTransport() {
const transport = useContext(TransportContext);
console.log("useTransport called, received:", transport);
if (!transport) {
throw new Error("useTransport must be used within a TransportProvider");
}
return transport;
}
export function useConnectQuery<
I extends DescMessage,
O extends DescMessage
>(
schema: DescMethodUnary<I, O>,
input?: MessageInitShape<I>,
options?: Omit<CreateQueryOptions<MessageShape<O>, ConnectError>, "queryKey" | "queryFn"> & {
transport?: Transport;
}
): CreateQueryResult<MessageShape<O>, ConnectError> {
const contextTransport = useTransport();
return createQuery(() => {
const transport = options?.transport ?? contextTransport;
const baseOptions = createQueryOptions(schema, input, { transport });
return {
...baseOptions,
...options,
} as any;
});
}

View File

@@ -1,8 +1,14 @@
import { QueryClient } from '@tanstack/solid-query'
import { QueryClient } from "@tanstack/solid-query";
import { createConnectTransport } from "@connectrpc/connect-web";
export function getContext() {
const queryClient = new QueryClient()
const queryClient = new QueryClient();
const transport = createConnectTransport({
baseUrl: "http://127.0.0.1:8080",
});
return {
queryClient,
}
transport,
};
}

View File

@@ -10,6 +10,7 @@
import { Route as rootRouteImport } from './routes/__root'
import { Route as TodoRouteImport } from './routes/todo'
import { Route as ShortenRouteImport } from './routes/shorten'
import { Route as IndexRouteImport } from './routes/index'
const TodoRoute = TodoRouteImport.update({
@@ -17,6 +18,11 @@ const TodoRoute = TodoRouteImport.update({
path: '/todo',
getParentRoute: () => rootRouteImport,
} as any)
const ShortenRoute = ShortenRouteImport.update({
id: '/shorten',
path: '/shorten',
getParentRoute: () => rootRouteImport,
} as any)
const IndexRoute = IndexRouteImport.update({
id: '/',
path: '/',
@@ -25,27 +31,31 @@ const IndexRoute = IndexRouteImport.update({
export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/shorten': typeof ShortenRoute
'/todo': typeof TodoRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
'/shorten': typeof ShortenRoute
'/todo': typeof TodoRoute
}
export interface FileRoutesById {
__root__: typeof rootRouteImport
'/': typeof IndexRoute
'/shorten': typeof ShortenRoute
'/todo': typeof TodoRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
fullPaths: '/' | '/todo'
fullPaths: '/' | '/shorten' | '/todo'
fileRoutesByTo: FileRoutesByTo
to: '/' | '/todo'
id: '__root__' | '/' | '/todo'
to: '/' | '/shorten' | '/todo'
id: '__root__' | '/' | '/shorten' | '/todo'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
ShortenRoute: typeof ShortenRoute
TodoRoute: typeof TodoRoute
}
@@ -58,6 +68,13 @@ declare module '@tanstack/solid-router' {
preLoaderRoute: typeof TodoRouteImport
parentRoute: typeof rootRouteImport
}
'/shorten': {
id: '/shorten'
path: '/shorten'
fullPath: '/shorten'
preLoaderRoute: typeof ShortenRouteImport
parentRoute: typeof rootRouteImport
}
'/': {
id: '/'
path: '/'
@@ -70,6 +87,7 @@ declare module '@tanstack/solid-router' {
const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
ShortenRoute: ShortenRoute,
TodoRoute: TodoRoute,
}
export const routeTree = rootRouteImport

View File

@@ -1,20 +1,17 @@
import { createRouter as createTanStackRouter } from "@tanstack/solid-router";
import { routeTree } from "./routeTree.gen";
// import { getContext } from './integrations/tanstack-query/provider'
import NotFound from "./components/NotFound";
import { QueryClient } from "@tanstack/solid-query";
import { ErrorComponent } from "./routes/__root";
import { getContext } from "./integrations/tanstack-query/provider";
import { setupRouterSsrQueryIntegration } from "@tanstack/solid-router-ssr-query";
const queryClient = new QueryClient();
export function getRouter() {
const context = getContext();
const router = createTanStackRouter({
routeTree,
context: getContext(),
context,
scrollRestoration: true,
defaultPreload: "intent",
@@ -26,7 +23,7 @@ export function getRouter() {
setupRouterSsrQueryIntegration({
router,
queryClient,
queryClient: context.queryClient,
});
return router;

View File

@@ -6,6 +6,8 @@ import {
} from "@tanstack/solid-router";
import { TanStackRouterDevtools } from "@tanstack/solid-router-devtools";
import { QueryClientProvider, QueryClient } from "@tanstack/solid-query";
import type { Transport } from "@connectrpc/connect";
import { TransportProvider } from "~/integrations/connect-query/solid";
import "@fontsource/inter/400.css";
@@ -18,6 +20,7 @@ import { ThemeProvider } from "~/components/theme-provider";
export interface MyRouterContext {
queryClient: QueryClient;
transport: Transport;
}
export function ErrorComponent({ error }: { error: Error }) {
@@ -35,6 +38,7 @@ export const Route = createRootRouteWithContext<MyRouterContext>()({
function RootComponent() {
const context = Route.useRouteContext();
console.log("Root context:", context());
return (
<html>
<head>
@@ -43,14 +47,16 @@ function RootComponent() {
</head>
<body>
<QueryClientProvider client={context().queryClient}>
<Suspense>
<ThemeProvider>
<Header />
<Outlet />
</ThemeProvider>
<TransportProvider transport={context().transport}>
<Suspense>
<ThemeProvider>
<Header />
<Outlet />
</ThemeProvider>
<TanStackRouterDevtools />
</Suspense>
<TanStackRouterDevtools />
</Suspense>
</TransportProvider>
</QueryClientProvider>
<Scripts />
</body>

30
src/routes/shorten.tsx Normal file
View File

@@ -0,0 +1,30 @@
import { useConnectQuery } from "~/integrations/connect-query/solid";
import { createFileRoute } from "@tanstack/solid-router";
import { listURLRedirections } from "~/gen/proto/shorten/v1/shorten-ShortenService_connectquery";
import { For, Match, Switch } from "solid-js";
export const Route = createFileRoute("/shorten")({
component: RouteComponent,
});
function RouteComponent() {
const query = useConnectQuery(listURLRedirections, {});
return (
<div>
<Switch fallback={<div>Loading...</div>}>
<Match when={query.isError}>
<div>Error: {query.error?.message}</div>
</Match>
<Match when={query.isLoading}>
<div>Loading...</div>
</Match>
<Match when={query.data}>
<For each={query.data?.urlRedirections}>
{(item) => <div>{item.url}</div>}
</For>
</Match>
</Switch>
</div>
);
}