create-croissant 0.1.44 → 0.1.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/package.json +1 -1
  2. package/template/.expo/README.md +13 -0
  3. package/template/.expo/devices.json +3 -0
  4. package/template/apps/desktop/.eslintcache +1 -0
  5. package/template/apps/mobile/app/(tabs)/_layout.tsx +21 -14
  6. package/template/apps/mobile/app/(tabs)/account.tsx +147 -0
  7. package/template/apps/mobile/app/(tabs)/explore.tsx +334 -104
  8. package/template/apps/mobile/app/(tabs)/index.tsx +99 -97
  9. package/template/apps/mobile/app/_layout.tsx +26 -7
  10. package/template/apps/mobile/app/index.tsx +136 -0
  11. package/template/apps/mobile/app/login.tsx +135 -0
  12. package/template/apps/mobile/app/signup.tsx +144 -0
  13. package/template/apps/mobile/app.json +3 -3
  14. package/template/apps/mobile/components/ui/button.tsx +86 -0
  15. package/template/apps/mobile/components/ui/input.tsx +56 -0
  16. package/template/apps/mobile/lib/orpc.ts +23 -0
  17. package/template/apps/mobile/package.json +13 -1
  18. package/template/apps/mobile/tsconfig.json +4 -1
  19. package/template/apps/platform/package.json +2 -1
  20. package/template/apps/platform/src/components/login-form.tsx +5 -4
  21. package/template/apps/platform/src/components/signup-form.tsx +12 -16
  22. package/template/apps/platform/src/routes/__root.tsx +6 -2
  23. package/template/apps/platform/src/routes/_auth/account.tsx +13 -17
  24. package/template/apps/platform/src/routes/_auth/examples/client-orpc-auth.tsx +2 -6
  25. package/template/apps/platform/src/routes/_public/examples/client-orpc.tsx +16 -29
  26. package/template/apps/platform/src/routes/_public/examples/ssr-orpc.tsx +10 -14
  27. package/template/apps/platform/src/routes/api/auth/$.ts +23 -2
  28. package/template/apps/platform/src/routes/api/rpc.$.ts +18 -0
  29. package/template/package.json +2 -2
  30. package/template/packages/orpc/package.json +7 -1
  31. package/template/packages/orpc/src/lib/planets.ts +18 -18
  32. package/template/packages/orpc/src/lib/router.ts +3 -3
  33. package/template/packages/orpc/src/react/context.tsx +23 -0
  34. package/template/packages/orpc/src/react/general.ts +29 -0
  35. package/template/packages/orpc/src/react/index.ts +3 -0
  36. package/template/packages/orpc/src/react/planets.ts +90 -0
  37. package/template/tsconfig.json +2 -1
  38. package/template/apps/mobile/app/modal.tsx +0 -29
@@ -18,12 +18,13 @@ import { Input } from "@workspace/ui/components/input";
18
18
  import { useState } from "react";
19
19
  import { Link } from "@tanstack/react-router";
20
20
  import { useForm } from "@tanstack/react-form";
21
- import { type } from "arktype";
21
+ import { z } from "zod";
22
+
22
23
  import { authClient } from "@/lib/auth-client";
23
24
 
24
- const loginSchema = type({
25
- email: "string.email",
26
- password: "string>0",
25
+ const loginSchema = z.object({
26
+ email: z.string().email("Invalid email address"),
27
+ password: z.string().min(8, "Password must be at least 8 characters"),
27
28
  });
28
29
 
29
30
  export function LoginForm({ className, ...props }: React.ComponentProps<"div">) {
@@ -17,24 +17,20 @@ import { Input } from "@workspace/ui/components/input";
17
17
  import { useState } from "react";
18
18
  import { Link } from "@tanstack/react-router";
19
19
  import { useForm } from "@tanstack/react-form";
20
- import { type } from "arktype";
20
+ import { z } from "zod";
21
21
  import { authClient } from "@/lib/auth-client";
22
22
 
23
- const signupSchema = type({
24
- name: "string>0",
25
- email: "string.email",
26
- password: "string>=8",
27
- confirmPassword: "string>0",
28
- }).narrow((data, ctx) => {
29
- if (data.password !== data.confirmPassword) {
30
- ctx.error({
31
- message: "Passwords do not match",
32
- path: ["confirmPassword"],
33
- });
34
- return false;
35
- }
36
- return true;
37
- });
23
+ const signupSchema = z
24
+ .object({
25
+ name: z.string().min(1, "Name is required"),
26
+ email: z.string().email("Invalid email address"),
27
+ password: z.string().min(8, "Password must be at least 8 characters"),
28
+ confirmPassword: z.string().min(1, "Confirm password is required"),
29
+ })
30
+ .refine((data) => data.password === data.confirmPassword, {
31
+ message: "Passwords do not match",
32
+ path: ["confirmPassword"],
33
+ });
38
34
 
39
35
  export function SignupForm({ ...props }: React.ComponentProps<typeof Card>) {
40
36
  const [loading, setLoading] = useState(false);
@@ -2,6 +2,8 @@ import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router";
2
2
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
3
3
  import { Toaster } from "@workspace/ui/components/sonner";
4
4
  import { ThemeProvider } from "@workspace/ui/components/theme-provider";
5
+ import { ORPCProvider } from "@workspace/orpc/react";
6
+ import { orpc } from "@/lib/orpc";
5
7
 
6
8
  import appCss from "@workspace/ui/globals.css?url";
7
9
 
@@ -40,8 +42,10 @@ function RootDocument({ children }: { children: React.ReactNode }) {
40
42
  <body>
41
43
  <ThemeProvider defaultTheme="system" storageKey="theme">
42
44
  <QueryClientProvider client={queryClient}>
43
- {children}
44
- <Toaster />
45
+ <ORPCProvider client={orpc}>
46
+ {children}
47
+ <Toaster />
48
+ </ORPCProvider>
45
49
  </QueryClientProvider>
46
50
  </ThemeProvider>
47
51
  <Scripts />
@@ -1,9 +1,9 @@
1
1
  import * as React from "react";
2
2
  import { createFileRoute, redirect } from "@tanstack/react-router";
3
3
  import { useForm } from "@tanstack/react-form";
4
+ import { z } from "zod";
4
5
  import { toast } from "sonner";
5
6
  import { Loader2, User } from "lucide-react";
6
- import { type } from "arktype";
7
7
 
8
8
  import { Button } from "@workspace/ui/components/button";
9
9
  import { Input } from "@workspace/ui/components/input";
@@ -22,24 +22,20 @@ import { Separator } from "@workspace/ui/components/separator";
22
22
  import { authClient } from "@/lib/auth-client";
23
23
  import { getSessionFn } from "@/lib/auth-utils";
24
24
 
25
- const profileSchema = type({
26
- name: "string>0",
25
+ const profileSchema = z.object({
26
+ name: z.string().min(1, "Name is required"),
27
27
  });
28
28
 
29
- const passwordSchema = type({
30
- currentPassword: "string>0",
31
- newPassword: "string>=8",
32
- confirmPassword: "string>0",
33
- }).narrow((data, ctx) => {
34
- if (data.newPassword !== data.confirmPassword) {
35
- ctx.error({
36
- message: "Passwords do not match",
37
- path: ["confirmPassword"],
38
- });
39
- return false;
40
- }
41
- return true;
42
- });
29
+ const passwordSchema = z
30
+ .object({
31
+ currentPassword: z.string().min(1, "Current password is required"),
32
+ newPassword: z.string().min(8, "New password must be at least 8 characters"),
33
+ confirmPassword: z.string().min(1, "Confirm password is required"),
34
+ })
35
+ .refine((data) => data.newPassword === data.confirmPassword, {
36
+ message: "Passwords do not match",
37
+ path: ["confirmPassword"],
38
+ });
43
39
 
44
40
  export const Route = createFileRoute("/_auth/account")({
45
41
  beforeLoad: async () => {
@@ -1,7 +1,6 @@
1
1
  import { createFileRoute, redirect } from "@tanstack/react-router";
2
- import { useQuery } from "@tanstack/react-query";
3
2
  import { getSessionFn } from "@/lib/auth-utils";
4
- import { orpc } from "@/lib/orpc";
3
+ import { useSecretData } from "@workspace/orpc/react";
5
4
 
6
5
  export const Route = createFileRoute("/_auth/examples/client-orpc-auth")({
7
6
  beforeLoad: async () => {
@@ -22,10 +21,7 @@ export const Route = createFileRoute("/_auth/examples/client-orpc-auth")({
22
21
  function ClientORPCAuth() {
23
22
  const { session } = Route.useRouteContext();
24
23
 
25
- const { data, isLoading } = useQuery({
26
- queryKey: ["secret-data"],
27
- queryFn: () => orpc.getSecretData(),
28
- });
24
+ const { data, isLoading } = useSecretData();
29
25
 
30
26
  return (
31
27
  <div className="flex flex-col gap-4">
@@ -2,9 +2,9 @@ import * as React from "react";
2
2
  import { createFileRoute } from "@tanstack/react-router";
3
3
  import { Check, Pencil, Plus, Trash2 } from "lucide-react";
4
4
  import { toast } from "sonner";
5
- import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
5
+ import { useQueryClient } from "@tanstack/react-query";
6
6
  import { useForm } from "@tanstack/react-form";
7
- import { type } from "arktype";
7
+ import { z } from "zod";
8
8
 
9
9
  import { Button } from "@workspace/ui/components/button";
10
10
  import { Input } from "@workspace/ui/components/input";
@@ -12,25 +12,21 @@ import { Field, FieldError, FieldLabel } from "@workspace/ui/components/field";
12
12
 
13
13
  import type { router } from "@workspace/orpc/router";
14
14
  import type { InferRouterInputs, InferRouterOutputs } from "@orpc/server";
15
- import { orpc } from "@/lib/orpc";
15
+ import { usePlanets, useCreatePlanet, useUpdatePlanet, useDeletePlanet } from "@workspace/orpc/react";
16
16
 
17
17
  type Inputs = InferRouterInputs<typeof router>;
18
18
  type Outputs = InferRouterOutputs<typeof router>;
19
19
  type Planet = Outputs["planets"]["getPlanets"][number];
20
20
 
21
- const planetSchema = type({
22
- name: "string>0",
23
- description: "string",
24
- distance: "string",
25
- diameter: "string",
26
- }).narrow((data, ctx) => {
27
- if (isNaN(parseFloat(data.distance))) {
28
- ctx.error({ message: "Must be a number", path: ["distance"] });
29
- }
30
- if (isNaN(parseFloat(data.diameter))) {
31
- ctx.error({ message: "Must be a number", path: ["diameter"] });
32
- }
33
- return true;
21
+ const planetSchema = z.object({
22
+ name: z.string().min(1),
23
+ description: z.string(),
24
+ distance: z.string().refine((val) => !isNaN(parseFloat(val)), {
25
+ message: "Must be a number",
26
+ }),
27
+ diameter: z.string().refine((val) => !isNaN(parseFloat(val)), {
28
+ message: "Must be a number",
29
+ }),
34
30
  });
35
31
 
36
32
  export const Route = createFileRoute("/_public/examples/client-orpc")({
@@ -52,10 +48,7 @@ function ClientORPC() {
52
48
  const queryClient = useQueryClient();
53
49
  const [editingId, setEditingId] = React.useState<number | null>(null);
54
50
 
55
- const { data: planets = [], isLoading } = useQuery({
56
- queryKey: ["planets"],
57
- queryFn: () => orpc.planets.getPlanets(),
58
- });
51
+ const { data: planets = [], isLoading } = usePlanets();
59
52
 
60
53
  const form = useForm({
61
54
  defaultValues: {
@@ -94,10 +87,8 @@ function ClientORPC() {
94
87
  setEditingId(null);
95
88
  };
96
89
 
97
- const createMutation = useMutation({
98
- mutationFn: (input: Inputs["planets"]["createPlanet"]) => orpc.planets.createPlanet(input),
90
+ const createMutation = useCreatePlanet({
99
91
  onSuccess: () => {
100
- queryClient.invalidateQueries({ queryKey: ["planets"] });
101
92
  resetForm();
102
93
  toast.success("Planet added successfully");
103
94
  },
@@ -106,10 +97,8 @@ function ClientORPC() {
106
97
  },
107
98
  });
108
99
 
109
- const updateMutation = useMutation({
110
- mutationFn: (input: Inputs["planets"]["updatePlanet"]) => orpc.planets.updatePlanet(input),
100
+ const updateMutation = useUpdatePlanet({
111
101
  onSuccess: () => {
112
- queryClient.invalidateQueries({ queryKey: ["planets"] });
113
102
  resetForm();
114
103
  toast.success("Planet updated successfully");
115
104
  },
@@ -118,10 +107,8 @@ function ClientORPC() {
118
107
  },
119
108
  });
120
109
 
121
- const deleteMutation = useMutation({
122
- mutationFn: (input: Inputs["planets"]["deletePlanet"]) => orpc.planets.deletePlanet(input),
110
+ const deleteMutation = useDeletePlanet({
123
111
  onSuccess: () => {
124
- queryClient.invalidateQueries({ queryKey: ["planets"] });
125
112
  toast.success("Planet deleted successfully");
126
113
  },
127
114
  onError: (err) => {
@@ -4,7 +4,7 @@ import { createServerFn } from "@tanstack/react-start";
4
4
  import { Check, Pencil, Plus, Trash2 } from "lucide-react";
5
5
  import { toast } from "sonner";
6
6
  import { useForm } from "@tanstack/react-form";
7
- import { type } from "arktype";
7
+ import { z } from "zod";
8
8
 
9
9
  import { Button } from "@workspace/ui/components/button";
10
10
  import { Input } from "@workspace/ui/components/input";
@@ -17,19 +17,15 @@ import { orpc } from "@/lib/orpc";
17
17
  type Outputs = InferRouterOutputs<typeof router>;
18
18
  type Planet = Outputs["planets"]["getPlanets"][number];
19
19
 
20
- const planetSchema = type({
21
- name: "string>0",
22
- description: "string",
23
- distance: "string",
24
- diameter: "string",
25
- }).narrow((data, ctx) => {
26
- if (isNaN(parseFloat(data.distance))) {
27
- ctx.error({ message: "Must be a number", path: ["distance"] });
28
- }
29
- if (isNaN(parseFloat(data.diameter))) {
30
- ctx.error({ message: "Must be a number", path: ["diameter"] });
31
- }
32
- return true;
20
+ const planetSchema = z.object({
21
+ name: z.string().min(1),
22
+ description: z.string(),
23
+ distance: z.string().refine((val) => !isNaN(parseFloat(val)), {
24
+ message: "Must be a number",
25
+ }),
26
+ diameter: z.string().refine((val) => !isNaN(parseFloat(val)), {
27
+ message: "Must be a number",
28
+ }),
33
29
  });
34
30
 
35
31
  const getPlanets = createServerFn({ method: "GET" }).handler(async () => {
@@ -1,14 +1,35 @@
1
1
  import { auth } from "@workspace/auth/lib/auth";
2
2
  import { createFileRoute } from "@tanstack/react-router";
3
3
 
4
+ const CORS_HEADERS = {
5
+ "Access-Control-Allow-Origin": "http://localhost:8081",
6
+ "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
7
+ "Access-Control-Allow-Headers": "Content-Type, Authorization",
8
+ "Access-Control-Allow-Credentials": "true",
9
+ };
10
+
4
11
  export const Route = createFileRoute("/api/auth/$")({
5
12
  server: {
6
13
  handlers: {
7
14
  GET: async ({ request }: { request: Request }) => {
8
- return await auth.handler(request);
15
+ const response = await auth.handler(request);
16
+ Object.entries(CORS_HEADERS).forEach(([key, value]) => {
17
+ response.headers.set(key, value);
18
+ });
19
+ return response;
9
20
  },
10
21
  POST: async ({ request }: { request: Request }) => {
11
- return await auth.handler(request);
22
+ const response = await auth.handler(request);
23
+ Object.entries(CORS_HEADERS).forEach(([key, value]) => {
24
+ response.headers.set(key, value);
25
+ });
26
+ return response;
27
+ },
28
+ OPTIONS: async () => {
29
+ return new Response(null, {
30
+ status: 204,
31
+ headers: CORS_HEADERS,
32
+ });
12
33
  },
13
34
  },
14
35
  },
@@ -27,8 +27,26 @@ export const Route = createFileRoute("/api/rpc/$")({
27
27
  },
28
28
  });
29
29
 
30
+ if (response) {
31
+ response.headers.set("Access-Control-Allow-Origin", "http://localhost:8081");
32
+ response.headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
33
+ response.headers.set("Access-Control-Allow-Headers", "Content-Type, Authorization");
34
+ response.headers.set("Access-Control-Allow-Credentials", "true");
35
+ }
36
+
30
37
  return response ?? new Response("Not Found", { status: 404 });
31
38
  },
39
+ OPTIONS: async () => {
40
+ return new Response(null, {
41
+ status: 204,
42
+ headers: {
43
+ "Access-Control-Allow-Origin": "http://localhost:8081",
44
+ "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
45
+ "Access-Control-Allow-Headers": "Content-Type, Authorization",
46
+ "Access-Control-Allow-Credentials": "true",
47
+ },
48
+ });
49
+ },
32
50
  },
33
51
  },
34
52
  });
@@ -31,13 +31,13 @@
31
31
  "@better-auth/core": "^1.6.9",
32
32
  "@types/react": "^19.2.7",
33
33
  "@types/react-dom": "^19.2.3",
34
- "arktype": "^2.2.0",
35
34
  "husky": "^9.1.7",
36
35
  "oxfmt": "^0.46.0",
37
36
  "oxlint": "^1.61.0",
38
37
  "turbo": "^2.9.6",
39
38
  "typescript": "6.0.3",
40
- "vite": "^8.0.10"
39
+ "vite": "^8.0.10",
40
+ "zod": "4.3.6"
41
41
  },
42
42
  "overrides": {
43
43
  "@noble/ciphers": "2.2.0",
@@ -4,7 +4,8 @@
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
7
- "./router": "./src/lib/router.ts"
7
+ "./router": "./src/lib/router.ts",
8
+ "./react": "./src/react/index.ts"
8
9
  },
9
10
  "scripts": {
10
11
  "typecheck": "tsc --noEmit"
@@ -12,9 +13,14 @@
12
13
  "dependencies": {
13
14
  "@orpc/client": "^1.14.0",
14
15
  "@orpc/server": "^1.14.0",
16
+ "@orpc/tanstack-query": "^1.14.0",
15
17
  "@workspace/auth": "*",
16
18
  "@workspace/db": "*"
17
19
  },
20
+ "peerDependencies": {
21
+ "@tanstack/react-query": "^5.100.5",
22
+ "react": ">=18"
23
+ },
18
24
  "devDependencies": {
19
25
  "@types/node": "^22.19.1",
20
26
  "@workspace/config-typescript": "*"
@@ -1,7 +1,7 @@
1
1
  import { ORPCError, os } from "@orpc/server";
2
2
  import { db, schema } from "@workspace/db";
3
3
  import { eq } from "drizzle-orm";
4
- import { type } from "arktype";
4
+ import { z } from "zod";
5
5
  import type { RPCContext } from "./router";
6
6
 
7
7
  const { planets } = schema;
@@ -16,13 +16,13 @@ export const planetRouter = o.router({
16
16
 
17
17
  createPlanet: o
18
18
  .input(
19
- type({
20
- name: "string>0",
21
- "description?": "string",
22
- distanceFromSun: "number",
23
- diameter: "number",
24
- "hasRings?": "boolean",
25
- "atmosphere?": "string",
19
+ z.object({
20
+ name: z.string().min(1),
21
+ description: z.string().optional(),
22
+ distanceFromSun: z.number(),
23
+ diameter: z.number(),
24
+ hasRings: z.boolean().optional(),
25
+ atmosphere: z.string().optional(),
26
26
  }),
27
27
  )
28
28
  .handler(async ({ input }) => {
@@ -32,14 +32,14 @@ export const planetRouter = o.router({
32
32
 
33
33
  updatePlanet: o
34
34
  .input(
35
- type({
36
- id: "number",
37
- name: "string>0",
38
- "description?": "string",
39
- distanceFromSun: "number",
40
- diameter: "number",
41
- hasRings: "boolean",
42
- "atmosphere?": "string",
35
+ z.object({
36
+ id: z.number(),
37
+ name: z.string().min(1),
38
+ description: z.string().optional(),
39
+ distanceFromSun: z.number(),
40
+ diameter: z.number(),
41
+ hasRings: z.boolean(),
42
+ atmosphere: z.string().optional(),
43
43
  }),
44
44
  )
45
45
  .handler(async ({ input }) => {
@@ -59,8 +59,8 @@ export const planetRouter = o.router({
59
59
 
60
60
  deletePlanet: o
61
61
  .input(
62
- type({
63
- id: "number",
62
+ z.object({
63
+ id: z.number(),
64
64
  }),
65
65
  )
66
66
  .handler(async ({ input }) => {
@@ -1,5 +1,5 @@
1
1
  import { ORPCError, os } from "@orpc/server";
2
- import { type } from "arktype";
2
+ import { z } from "zod";
3
3
  import { planetRouter } from "./planets";
4
4
  import type { Session } from "@workspace/auth/lib/auth";
5
5
 
@@ -14,8 +14,8 @@ export const router = o.router({
14
14
 
15
15
  hello: o
16
16
  .input(
17
- type({
18
- "name?": "string",
17
+ z.object({
18
+ name: z.string().optional(),
19
19
  }),
20
20
  )
21
21
  .handler(({ input }) => {
@@ -0,0 +1,23 @@
1
+ import * as React from "react";
2
+ import type { RouterClient } from "@orpc/server";
3
+ import type { AppRouter } from "../lib/router";
4
+
5
+ const ORPCContext = React.createContext<RouterClient<AppRouter> | null>(null);
6
+
7
+ export function ORPCProvider({
8
+ client,
9
+ children,
10
+ }: {
11
+ client: RouterClient<AppRouter>;
12
+ children: React.ReactNode;
13
+ }) {
14
+ return <ORPCContext.Provider value={client}>{children}</ORPCContext.Provider>;
15
+ }
16
+
17
+ export function useORPC() {
18
+ const context = React.useContext(ORPCContext);
19
+ if (!context) {
20
+ throw new Error("useORPC must be used within an ORPCProvider");
21
+ }
22
+ return context;
23
+ }
@@ -0,0 +1,29 @@
1
+ import { useQuery, type UseQueryOptions } from "@tanstack/react-query";
2
+ import type { AppRouter } from "../lib/router";
3
+ import type { InferRouterOutputs } from "@orpc/server";
4
+ import { useORPC } from "./context";
5
+
6
+ type Outputs = InferRouterOutputs<AppRouter>;
7
+
8
+ export function useSecretData(
9
+ options?: Omit<UseQueryOptions<Outputs["getSecretData"]>, "queryKey" | "queryFn">,
10
+ ) {
11
+ const orpc = useORPC();
12
+ return useQuery({
13
+ ...options,
14
+ queryKey: ["secret-data"],
15
+ queryFn: () => orpc.getSecretData(),
16
+ });
17
+ }
18
+
19
+ export function useHello(
20
+ name?: string,
21
+ options?: Omit<UseQueryOptions<Outputs["hello"]>, "queryKey" | "queryFn">,
22
+ ) {
23
+ const orpc = useORPC();
24
+ return useQuery({
25
+ ...options,
26
+ queryKey: ["hello", name],
27
+ queryFn: () => orpc.hello({ name }),
28
+ });
29
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./context";
2
+ export * from "./planets";
3
+ export * from "./general";
@@ -0,0 +1,90 @@
1
+ import {
2
+ useMutation,
3
+ useQuery,
4
+ useQueryClient,
5
+ type UseMutationOptions,
6
+ type UseQueryOptions,
7
+ } from "@tanstack/react-query";
8
+ import type { AppRouter } from "../lib/router";
9
+ import type { InferRouterInputs, InferRouterOutputs } from "@orpc/server";
10
+ import { useORPC } from "./context";
11
+
12
+ type Inputs = InferRouterInputs<AppRouter>;
13
+ type Outputs = InferRouterOutputs<AppRouter>;
14
+
15
+ export function usePlanets(
16
+ options?: Omit<UseQueryOptions<Outputs["planets"]["getPlanets"]>, "queryKey" | "queryFn">,
17
+ ) {
18
+ const orpc = useORPC();
19
+ return useQuery({
20
+ ...options,
21
+ queryKey: ["planets"],
22
+ queryFn: () => orpc.planets.getPlanets(),
23
+ });
24
+ }
25
+
26
+ export function useCreatePlanet(
27
+ options?: Omit<
28
+ UseMutationOptions<
29
+ Outputs["planets"]["createPlanet"],
30
+ Error,
31
+ Inputs["planets"]["createPlanet"]
32
+ >,
33
+ "mutationFn"
34
+ >,
35
+ ) {
36
+ const orpc = useORPC();
37
+ const queryClient = useQueryClient();
38
+ return useMutation({
39
+ ...options,
40
+ mutationFn: (input: Inputs["planets"]["createPlanet"]) => orpc.planets.createPlanet(input),
41
+ onSuccess: (data, variables, context, extra) => {
42
+ queryClient.invalidateQueries({ queryKey: ["planets"] });
43
+ options?.onSuccess?.(data, variables, context, extra);
44
+ },
45
+ });
46
+ }
47
+
48
+ export function useUpdatePlanet(
49
+ options?: Omit<
50
+ UseMutationOptions<
51
+ Outputs["planets"]["updatePlanet"],
52
+ Error,
53
+ Inputs["planets"]["updatePlanet"]
54
+ >,
55
+ "mutationFn"
56
+ >,
57
+ ) {
58
+ const orpc = useORPC();
59
+ const queryClient = useQueryClient();
60
+ return useMutation({
61
+ ...options,
62
+ mutationFn: (input: Inputs["planets"]["updatePlanet"]) => orpc.planets.updatePlanet(input),
63
+ onSuccess: (data, variables, context, extra) => {
64
+ queryClient.invalidateQueries({ queryKey: ["planets"] });
65
+ options?.onSuccess?.(data, variables, context, extra);
66
+ },
67
+ });
68
+ }
69
+
70
+ export function useDeletePlanet(
71
+ options?: Omit<
72
+ UseMutationOptions<
73
+ Outputs["planets"]["deletePlanet"],
74
+ Error,
75
+ Inputs["planets"]["deletePlanet"]
76
+ >,
77
+ "mutationFn"
78
+ >,
79
+ ) {
80
+ const orpc = useORPC();
81
+ const queryClient = useQueryClient();
82
+ return useMutation({
83
+ ...options,
84
+ mutationFn: (input: Inputs["planets"]["deletePlanet"]) => orpc.planets.deletePlanet(input),
85
+ onSuccess: (data, variables, context, extra) => {
86
+ queryClient.invalidateQueries({ queryKey: ["planets"] });
87
+ options?.onSuccess?.(data, variables, context, extra);
88
+ },
89
+ });
90
+ }
@@ -5,5 +5,6 @@
5
5
  "moduleResolution": "bundler",
6
6
  "skipLibCheck": true,
7
7
  "strict": true
8
- }
8
+ },
9
+ "extends": "expo/tsconfig.base"
9
10
  }
@@ -1,29 +0,0 @@
1
- import { Link } from "expo-router";
2
- import { StyleSheet } from "react-native";
3
-
4
- import { ThemedText } from "@/components/themed-text";
5
- import { ThemedView } from "@/components/themed-view";
6
-
7
- export default function ModalScreen() {
8
- return (
9
- <ThemedView style={styles.container}>
10
- <ThemedText type="title">This is a modal</ThemedText>
11
- <Link href="/" dismissTo style={styles.link}>
12
- <ThemedText type="link">Go to home screen</ThemedText>
13
- </Link>
14
- </ThemedView>
15
- );
16
- }
17
-
18
- const styles = StyleSheet.create({
19
- container: {
20
- flex: 1,
21
- alignItems: "center",
22
- justifyContent: "center",
23
- padding: 20,
24
- },
25
- link: {
26
- marginTop: 15,
27
- paddingVertical: 15,
28
- },
29
- });