@tanstack/create 0.49.2 → 0.49.3

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 (76) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/frameworks/react/add-ons/ai/assets/src/data/demo-guitars.ts +93 -0
  3. package/dist/frameworks/react/add-ons/ai/assets/src/hooks/demo-useAudioRecorder.ts +85 -0
  4. package/dist/frameworks/react/add-ons/ai/assets/src/hooks/demo-useTTS.ts +78 -0
  5. package/dist/frameworks/react/add-ons/ai/assets/src/lib/demo-ai-hook.ts +22 -0
  6. package/dist/frameworks/react/add-ons/ai/assets/src/lib/demo-guitar-tools.ts +40 -0
  7. package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.chat.ts +99 -0
  8. package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.image.ts +72 -0
  9. package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.structured.ts +136 -0
  10. package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.transcription.ts +89 -0
  11. package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/api.ai.tts.ts +81 -0
  12. package/dist/frameworks/react/add-ons/better-auth/assets/src/lib/auth-client.ts +3 -0
  13. package/dist/frameworks/react/add-ons/better-auth/assets/src/lib/auth.ts +9 -0
  14. package/dist/frameworks/react/add-ons/better-auth/assets/src/routes/api/auth/$.ts +11 -0
  15. package/dist/frameworks/react/add-ons/convex/assets/convex/schema.ts +14 -0
  16. package/dist/frameworks/react/add-ons/convex/assets/convex/todos.ts +43 -0
  17. package/dist/frameworks/react/add-ons/db/assets/src/db-collections/index.ts +20 -0
  18. package/dist/frameworks/react/add-ons/db/assets/src/hooks/demo.useChat.ts +62 -0
  19. package/dist/frameworks/react/add-ons/db/assets/src/routes/demo/db-chat-api.ts +83 -0
  20. package/dist/frameworks/react/add-ons/form/assets/src/hooks/demo.form-context.ts +4 -0
  21. package/dist/frameworks/react/add-ons/form/assets/src/hooks/demo.form.ts +22 -0
  22. package/dist/frameworks/react/add-ons/mcp/assets/src/mcp-todos.ts +51 -0
  23. package/dist/frameworks/react/add-ons/mcp/assets/src/routes/demo/api.mcp-todos.ts +37 -0
  24. package/dist/frameworks/react/add-ons/mcp/assets/src/routes/mcp.ts +53 -0
  25. package/dist/frameworks/react/add-ons/mcp/assets/src/utils/mcp-handler.ts +61 -0
  26. package/dist/frameworks/react/add-ons/neon/assets/neon-vite-plugin.ts +10 -0
  27. package/dist/frameworks/react/add-ons/neon/assets/src/db.ts +13 -0
  28. package/dist/frameworks/react/add-ons/oRPC/assets/src/orpc/client.ts +29 -0
  29. package/dist/frameworks/react/add-ons/oRPC/assets/src/orpc/router/index.ts +6 -0
  30. package/dist/frameworks/react/add-ons/oRPC/assets/src/orpc/router/todos.ts +20 -0
  31. package/dist/frameworks/react/add-ons/oRPC/assets/src/orpc/schema.ts +6 -0
  32. package/dist/frameworks/react/add-ons/oRPC/assets/src/polyfill.ts +21 -0
  33. package/dist/frameworks/react/add-ons/oRPC/assets/src/routes/api.$.ts +77 -0
  34. package/dist/frameworks/react/add-ons/oRPC/assets/src/routes/api.rpc.$.ts +29 -0
  35. package/dist/frameworks/react/add-ons/shadcn/assets/src/lib/utils.ts +6 -0
  36. package/dist/frameworks/react/add-ons/start/assets/src/data/demo.punk-songs.ts +13 -0
  37. package/dist/frameworks/react/add-ons/start/assets/src/routes/demo/api.names.ts +10 -0
  38. package/dist/frameworks/react/add-ons/store/assets/src/lib/demo-store.ts +13 -0
  39. package/dist/frameworks/react/add-ons/storybook/assets/_dot_storybook/main.ts +17 -0
  40. package/dist/frameworks/react/add-ons/storybook/assets/_dot_storybook/preview.ts +15 -0
  41. package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/button.stories.ts +67 -0
  42. package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/index.ts +14 -0
  43. package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/input.stories.ts +43 -0
  44. package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/radio-group.stories.ts +53 -0
  45. package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/slider.stories.ts +55 -0
  46. package/dist/frameworks/react/add-ons/strapi/assets/src/lib/strapiClient.ts +7 -0
  47. package/dist/frameworks/react/add-ons/t3env/assets/src/env.ts +39 -0
  48. package/dist/frameworks/react/add-ons/tRPC/assets/src/integrations/trpc/init.ts +9 -0
  49. package/dist/frameworks/react/add-ons/tRPC/assets/src/integrations/trpc/react.ts +4 -0
  50. package/dist/frameworks/react/add-ons/tRPC/assets/src/integrations/trpc/router.ts +27 -0
  51. package/dist/frameworks/react/add-ons/table/assets/src/data/demo-table-data.ts +50 -0
  52. package/dist/frameworks/react/examples/events/assets/content-collections.ts +56 -0
  53. package/dist/frameworks/react/examples/events/assets/src/lib/conference-ai-hook.ts +26 -0
  54. package/dist/frameworks/react/examples/events/assets/src/lib/conference-tools.ts +210 -0
  55. package/dist/frameworks/react/examples/events/assets/src/lib/utils.ts +6 -0
  56. package/dist/frameworks/react/examples/events/assets/src/routes/api.remy-chat.ts +121 -0
  57. package/dist/frameworks/react/examples/resume/assets/content-collections.ts +36 -0
  58. package/dist/frameworks/react/examples/resume/assets/src/lib/resume-ai-hook.ts +21 -0
  59. package/dist/frameworks/react/examples/resume/assets/src/lib/resume-tools.ts +165 -0
  60. package/dist/frameworks/react/examples/resume/assets/src/lib/utils.ts +6 -0
  61. package/dist/frameworks/react/examples/resume/assets/src/routes/api.resume-chat.ts +110 -0
  62. package/dist/frameworks/solid/add-ons/better-auth/assets/src/lib/auth-client.ts +3 -0
  63. package/dist/frameworks/solid/add-ons/better-auth/assets/src/lib/auth.ts +9 -0
  64. package/dist/frameworks/solid/add-ons/better-auth/assets/src/routes/api/auth/$.ts +11 -0
  65. package/dist/frameworks/solid/add-ons/convex/assets/convex/schema.ts +14 -0
  66. package/dist/frameworks/solid/add-ons/convex/assets/convex/todos.ts +43 -0
  67. package/dist/frameworks/solid/add-ons/solid-ui/assets/src/lib/utils.ts +6 -0
  68. package/dist/frameworks/solid/add-ons/store/assets/src/lib/demo-store.ts +13 -0
  69. package/dist/frameworks/solid/add-ons/strapi/assets/src/lib/strapiClient.ts +7 -0
  70. package/dist/frameworks/solid/add-ons/t3env/assets/src/env.ts +39 -0
  71. package/dist/frameworks/solid/examples/tanchat/assets/ai-streaming-server/src/index.ts +102 -0
  72. package/dist/frameworks/solid/examples/tanchat/assets/src/lib/demo-store.ts +13 -0
  73. package/dist/frameworks/solid/examples/tanchat/assets/src/store/demo.hooks.ts +17 -0
  74. package/dist/frameworks/solid/examples/tanchat/assets/src/store/demo.store.ts +133 -0
  75. package/package.json +2 -2
  76. package/tests/copy-assets.test.ts +53 -0
@@ -0,0 +1,29 @@
1
+ import { createRouterClient } from '@orpc/server'
2
+ import { createORPCClient } from '@orpc/client'
3
+ import { RPCLink } from '@orpc/client/fetch'
4
+ import { createTanstackQueryUtils } from '@orpc/tanstack-query'
5
+ import { getRequestHeaders } from '@tanstack/react-start/server'
6
+ import { createIsomorphicFn } from '@tanstack/react-start'
7
+
8
+ import type { RouterClient } from '@orpc/server'
9
+
10
+ import router from '@/orpc/router'
11
+
12
+ const getORPCClient = createIsomorphicFn()
13
+ .server(() =>
14
+ createRouterClient(router, {
15
+ context: () => ({
16
+ headers: getRequestHeaders(),
17
+ }),
18
+ }),
19
+ )
20
+ .client((): RouterClient<typeof router> => {
21
+ const link = new RPCLink({
22
+ url: `${window.location.origin}/api/rpc`,
23
+ })
24
+ return createORPCClient(link)
25
+ })
26
+
27
+ export const client: RouterClient<typeof router> = getORPCClient()
28
+
29
+ export const orpc = createTanstackQueryUtils(client)
@@ -0,0 +1,6 @@
1
+ import { addTodo, listTodos } from './todos'
2
+
3
+ export default {
4
+ listTodos,
5
+ addTodo,
6
+ }
@@ -0,0 +1,20 @@
1
+ import { os } from '@orpc/server'
2
+ import * as z from 'zod'
3
+
4
+ const todos = [
5
+ { id: 1, name: 'Get groceries' },
6
+ { id: 2, name: 'Buy a new phone' },
7
+ { id: 3, name: 'Finish the project' },
8
+ ]
9
+
10
+ export const listTodos = os.input(z.object({})).handler(() => {
11
+ return todos
12
+ })
13
+
14
+ export const addTodo = os
15
+ .input(z.object({ name: z.string() }))
16
+ .handler(({ input }) => {
17
+ const newTodo = { id: todos.length + 1, name: input.name }
18
+ todos.push(newTodo)
19
+ return newTodo
20
+ })
@@ -0,0 +1,6 @@
1
+ import { z } from 'zod'
2
+
3
+ export const TodoSchema = z.object({
4
+ id: z.number().int().min(1),
5
+ name: z.string(),
6
+ })
@@ -0,0 +1,21 @@
1
+ import { File } from "node:buffer";
2
+
3
+ /**
4
+ * This file aims to polyfill missing APIs in Node.js 18 that oRPC depends on.
5
+ *
6
+ * Since Stackblitz runs on Node.js 18, these polyfills ensure oRPC works in that environment.
7
+ * If you're running oRPC locally, please use Node.js 20 or later for full compatibility.
8
+ */
9
+
10
+ /**
11
+ * Note: Stackblitz provides an emulated Node.js environment with inherent limitations.
12
+ * If you encounter issues, please test on a local setup with Node.js 20 or later before reporting them.
13
+ */
14
+
15
+ /**
16
+ * The `oz.file()` schema depends on the `File` API.
17
+ * If you're not using `oz.file()`, you can safely remove this polyfill.
18
+ */
19
+ if (typeof globalThis.File === "undefined") {
20
+ globalThis.File = File as any;
21
+ }
@@ -0,0 +1,77 @@
1
+ import '@/polyfill'
2
+
3
+ import { OpenAPIHandler } from '@orpc/openapi/fetch'
4
+ import { ZodToJsonSchemaConverter } from '@orpc/zod/zod4'
5
+ import { SmartCoercionPlugin } from '@orpc/json-schema'
6
+ import { createFileRoute } from '@tanstack/react-router'
7
+ import { onError } from '@orpc/server'
8
+ import { OpenAPIReferencePlugin } from '@orpc/openapi/plugins'
9
+
10
+ import { TodoSchema } from '@/orpc/schema'
11
+ import router from '@/orpc/router'
12
+
13
+ const handler = new OpenAPIHandler(router, {
14
+ interceptors: [
15
+ onError((error) => {
16
+ console.error(error)
17
+ }),
18
+ ],
19
+ plugins: [
20
+ new SmartCoercionPlugin({
21
+ schemaConverters: [new ZodToJsonSchemaConverter()],
22
+ }),
23
+ new OpenAPIReferencePlugin({
24
+ schemaConverters: [new ZodToJsonSchemaConverter()],
25
+ specGenerateOptions: {
26
+ info: {
27
+ title: 'TanStack ORPC Playground',
28
+ version: '1.0.0',
29
+ },
30
+ commonSchemas: {
31
+ Todo: { schema: TodoSchema },
32
+ UndefinedError: { error: 'UndefinedError' },
33
+ },
34
+ security: [{ bearerAuth: [] }],
35
+ components: {
36
+ securitySchemes: {
37
+ bearerAuth: {
38
+ type: 'http',
39
+ scheme: 'bearer',
40
+ },
41
+ },
42
+ },
43
+ },
44
+ docsConfig: {
45
+ authentication: {
46
+ securitySchemes: {
47
+ bearerAuth: {
48
+ token: 'default-token',
49
+ },
50
+ },
51
+ },
52
+ },
53
+ }),
54
+ ],
55
+ })
56
+
57
+ async function handle({ request }: { request: Request }) {
58
+ const { response } = await handler.handle(request, {
59
+ prefix: '/api',
60
+ context: {},
61
+ })
62
+
63
+ return response ?? new Response('Not Found', { status: 404 })
64
+ }
65
+
66
+ export const Route = createFileRoute('/api/$')({
67
+ server: {
68
+ handlers: {
69
+ HEAD: handle,
70
+ GET: handle,
71
+ POST: handle,
72
+ PUT: handle,
73
+ PATCH: handle,
74
+ DELETE: handle,
75
+ },
76
+ },
77
+ })
@@ -0,0 +1,29 @@
1
+ import '@/polyfill'
2
+
3
+ import { RPCHandler } from '@orpc/server/fetch'
4
+ import { createFileRoute } from '@tanstack/react-router'
5
+ import router from '@/orpc/router'
6
+
7
+ const handler = new RPCHandler(router)
8
+
9
+ async function handle({ request }: { request: Request }) {
10
+ const { response } = await handler.handle(request, {
11
+ prefix: '/api/rpc',
12
+ context: {},
13
+ })
14
+
15
+ return response ?? new Response('Not Found', { status: 404 })
16
+ }
17
+
18
+ export const Route = createFileRoute('/api/rpc/$')({
19
+ server: {
20
+ handlers: {
21
+ HEAD: handle,
22
+ GET: handle,
23
+ POST: handle,
24
+ PUT: handle,
25
+ PATCH: handle,
26
+ DELETE: handle,
27
+ },
28
+ },
29
+ })
@@ -0,0 +1,6 @@
1
+ import { clsx, type ClassValue } from "clsx"
2
+ import { twMerge } from "tailwind-merge"
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs))
6
+ }
@@ -0,0 +1,13 @@
1
+ import { createServerFn } from "@tanstack/react-start";
2
+
3
+ export const getPunkSongs = createServerFn({
4
+ method: "GET",
5
+ }).handler(async () => [
6
+ { id: 1, name: "Teenage Dirtbag", artist: "Wheatus" },
7
+ { id: 2, name: "Smells Like Teen Spirit", artist: "Nirvana" },
8
+ { id: 3, name: "The Middle", artist: "Jimmy Eat World" },
9
+ { id: 4, name: "My Own Worst Enemy", artist: "Lit" },
10
+ { id: 5, name: "Fat Lip", artist: "Sum 41" },
11
+ { id: 6, name: "All the Small Things", artist: "blink-182" },
12
+ { id: 7, name: "Beverly Hills", artist: "Weezer" },
13
+ ]);
@@ -0,0 +1,10 @@
1
+ import { createFileRoute } from '@tanstack/react-router'
2
+ import { json } from '@tanstack/react-start'
3
+
4
+ export const Route = createFileRoute('/demo/api/names')({
5
+ server: {
6
+ handlers: {
7
+ GET: () => json(['Alice', 'Bob', 'Charlie']),
8
+ },
9
+ },
10
+ })
@@ -0,0 +1,13 @@
1
+ import { Derived, Store } from '@tanstack/store'
2
+
3
+ export const store = new Store({
4
+ firstName: 'Jane',
5
+ lastName: 'Smith',
6
+ })
7
+
8
+ export const fullName = new Derived({
9
+ fn: () => `${store.state.firstName} ${store.state.lastName}`,
10
+ deps: [store],
11
+ })
12
+
13
+ fullName.mount()
@@ -0,0 +1,17 @@
1
+ import type { StorybookConfig } from "@storybook/react-vite";
2
+
3
+ const config: StorybookConfig = {
4
+ stories: ["../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
5
+ addons: [],
6
+ framework: {
7
+ name: "@storybook/react-vite",
8
+ options: {},
9
+ },
10
+ async viteFinal(config) {
11
+ const { default: tailwindcss } = await import("@tailwindcss/vite");
12
+ config.plugins = config.plugins || [];
13
+ config.plugins.push(tailwindcss());
14
+ return config;
15
+ },
16
+ };
17
+ export default config;
@@ -0,0 +1,15 @@
1
+ import type { Preview } from "@storybook/react-vite";
2
+ import "../src/styles.css";
3
+
4
+ const preview: Preview = {
5
+ parameters: {
6
+ controls: {
7
+ matchers: {
8
+ color: /(background|color)$/i,
9
+ date: /Date$/i,
10
+ },
11
+ },
12
+ },
13
+ };
14
+
15
+ export default preview;
@@ -0,0 +1,67 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { fn } from "storybook/test";
3
+
4
+ import { Button } from "./button";
5
+
6
+ const meta = {
7
+ title: "Form/Button",
8
+ component: Button,
9
+ parameters: {
10
+ layout: "centered",
11
+ },
12
+ tags: ["autodocs"],
13
+ args: { onClick: fn() },
14
+ } satisfies Meta<typeof Button>;
15
+
16
+ export default meta;
17
+ type Story = StoryObj<typeof meta>;
18
+
19
+ export const Primary: Story = {
20
+ args: {
21
+ variant: "primary",
22
+ children: "Primary Button",
23
+ },
24
+ };
25
+
26
+ export const Secondary: Story = {
27
+ args: {
28
+ variant: "secondary",
29
+ children: "Secondary Button",
30
+ },
31
+ };
32
+
33
+ export const Danger: Story = {
34
+ args: {
35
+ variant: "danger",
36
+ children: "Delete Account",
37
+ },
38
+ };
39
+
40
+ export const Small: Story = {
41
+ args: {
42
+ size: "small",
43
+ children: "Small Button",
44
+ },
45
+ };
46
+
47
+ export const Medium: Story = {
48
+ args: {
49
+ size: "medium",
50
+ children: "Medium Button",
51
+ },
52
+ };
53
+
54
+ export const Large: Story = {
55
+ args: {
56
+ size: "large",
57
+ children: "Large Button",
58
+ },
59
+ };
60
+
61
+ export const Disabled: Story = {
62
+ args: {
63
+ variant: "primary",
64
+ children: "Disabled Button",
65
+ disabled: true,
66
+ },
67
+ };
@@ -0,0 +1,14 @@
1
+ export { Input } from "./input";
2
+ export type { InputProps } from "./input";
3
+
4
+ export { RadioGroup } from "./radio-group";
5
+ export type { RadioGroupProps, RadioOption } from "./radio-group";
6
+
7
+ export { Slider } from "./slider";
8
+ export type { SliderProps } from "./slider";
9
+
10
+ export { Dialog } from "./dialog";
11
+ export type { DialogProps } from "./dialog";
12
+
13
+ export { Button } from "./button";
14
+ export type { ButtonProps } from "./button";
@@ -0,0 +1,43 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { fn } from "storybook/test";
3
+
4
+ import { Input } from "./input";
5
+
6
+ const meta = {
7
+ title: "Form/Input",
8
+ component: Input,
9
+ parameters: {
10
+ layout: "centered",
11
+ },
12
+ tags: ["autodocs"],
13
+ args: { onChange: fn() },
14
+ } satisfies Meta<typeof Input>;
15
+
16
+ export default meta;
17
+ type Story = StoryObj<typeof meta>;
18
+
19
+ export const Default: Story = {
20
+ args: {
21
+ label: "Email Address",
22
+ id: "email",
23
+ placeholder: "Enter your email",
24
+ },
25
+ };
26
+
27
+ export const Required: Story = {
28
+ args: {
29
+ label: "First Name",
30
+ id: "firstName",
31
+ placeholder: "John",
32
+ required: true,
33
+ },
34
+ };
35
+
36
+ export const WithValue: Story = {
37
+ args: {
38
+ label: "Last Name",
39
+ id: "lastName",
40
+ value: "Doe",
41
+ placeholder: "Enter last name",
42
+ },
43
+ };
@@ -0,0 +1,53 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { fn } from "storybook/test";
3
+
4
+ import { RadioGroup } from "./radio-group";
5
+
6
+ const meta = {
7
+ title: "Form/RadioGroup",
8
+ component: RadioGroup,
9
+ parameters: {
10
+ layout: "centered",
11
+ },
12
+ tags: ["autodocs"],
13
+ args: { onChange: fn() },
14
+ } satisfies Meta<typeof RadioGroup>;
15
+
16
+ export default meta;
17
+ type Story = StoryObj<typeof meta>;
18
+
19
+ export const Default: Story = {
20
+ args: {
21
+ label: "Employment Type",
22
+ name: "employmentType",
23
+ options: [
24
+ { value: "full-time", label: "Full Time" },
25
+ { value: "part-time", label: "Part Time" },
26
+ ],
27
+ },
28
+ };
29
+
30
+ export const Selected: Story = {
31
+ args: {
32
+ label: "Employment Type",
33
+ name: "employmentType",
34
+ options: [
35
+ { value: "full-time", label: "Full Time" },
36
+ { value: "part-time", label: "Part Time" },
37
+ ],
38
+ value: "full-time",
39
+ },
40
+ };
41
+
42
+ export const MultipleOptions: Story = {
43
+ args: {
44
+ label: "Subscription Plan",
45
+ name: "plan",
46
+ options: [
47
+ { value: "basic", label: "Basic" },
48
+ { value: "pro", label: "Pro" },
49
+ { value: "enterprise", label: "Enterprise" },
50
+ ],
51
+ value: "pro",
52
+ },
53
+ };
@@ -0,0 +1,55 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { fn } from "storybook/test";
3
+
4
+ import { Slider } from "./slider";
5
+
6
+ const meta = {
7
+ title: "Form/Slider",
8
+ component: Slider,
9
+ parameters: {
10
+ layout: "centered",
11
+ },
12
+ tags: ["autodocs"],
13
+ args: { onChange: fn() },
14
+ } satisfies Meta<typeof Slider>;
15
+
16
+ export default meta;
17
+ type Story = StoryObj<typeof meta>;
18
+
19
+ export const Default: Story = {
20
+ args: {
21
+ label: "Volume",
22
+ id: "volume",
23
+ value: 50,
24
+ },
25
+ };
26
+
27
+ export const Skill: Story = {
28
+ args: {
29
+ label: "Plays Guitar",
30
+ id: "guitar",
31
+ value: 75,
32
+ min: 0,
33
+ max: 100,
34
+ },
35
+ };
36
+
37
+ export const NoValue: Story = {
38
+ args: {
39
+ label: "Experience Level",
40
+ id: "experience",
41
+ value: 30,
42
+ showValue: false,
43
+ },
44
+ };
45
+
46
+ export const CustomRange: Story = {
47
+ args: {
48
+ label: "Custom Range",
49
+ id: "custom-range",
50
+ value: 5,
51
+ min: 1,
52
+ max: 20,
53
+ step: 1,
54
+ },
55
+ };
@@ -0,0 +1,7 @@
1
+ import { strapi } from "@strapi/client";
2
+
3
+ export const strapiClient = strapi({
4
+ baseURL: import.meta.env.VITE_STRAPI_URL,
5
+ });
6
+
7
+ export const articles = strapiClient.collection("articles");
@@ -0,0 +1,39 @@
1
+ import { createEnv } from "@t3-oss/env-core";
2
+ import { z } from "zod";
3
+
4
+ export const env = createEnv({
5
+ server: {
6
+ SERVER_URL: z.string().url().optional(),
7
+ },
8
+
9
+ /**
10
+ * The prefix that client-side variables must have. This is enforced both at
11
+ * a type-level and at runtime.
12
+ */
13
+ clientPrefix: "VITE_",
14
+
15
+ client: {
16
+ VITE_APP_TITLE: z.string().min(1).optional(),
17
+ },
18
+
19
+ /**
20
+ * What object holds the environment variables at runtime. This is usually
21
+ * `process.env` or `import.meta.env`.
22
+ */
23
+ runtimeEnv: import.meta.env,
24
+
25
+ /**
26
+ * By default, this library will feed the environment variables directly to
27
+ * the Zod validator.
28
+ *
29
+ * This means that if you have an empty string for a value that is supposed
30
+ * to be a number (e.g. `PORT=` in a ".env" file), Zod will incorrectly flag
31
+ * it as a type mismatch violation. Additionally, if you have an empty string
32
+ * for a value that is supposed to be a string with a default value (e.g.
33
+ * `DOMAIN=` in an ".env" file), the default value will never be applied.
34
+ *
35
+ * In order to solve these issues, we recommend that all new projects
36
+ * explicitly specify this option as true.
37
+ */
38
+ emptyStringAsUndefined: true,
39
+ });
@@ -0,0 +1,9 @@
1
+ import { initTRPC } from "@trpc/server";
2
+ import superjson from "superjson";
3
+
4
+ const t = initTRPC.create({
5
+ transformer: superjson,
6
+ });
7
+
8
+ export const createTRPCRouter = t.router;
9
+ export const publicProcedure = t.procedure;
@@ -0,0 +1,4 @@
1
+ import { createTRPCContext } from "@trpc/tanstack-react-query";
2
+ import type { TRPCRouter } from "@/integrations/trpc/router";
3
+
4
+ export const { TRPCProvider, useTRPC } = createTRPCContext<TRPCRouter>();
@@ -0,0 +1,27 @@
1
+ import { z } from 'zod'
2
+
3
+ import { createTRPCRouter, publicProcedure } from './init'
4
+
5
+ import type { TRPCRouterRecord } from '@trpc/server'
6
+
7
+ const todos = [
8
+ { id: 1, name: 'Get groceries' },
9
+ { id: 2, name: 'Buy a new phone' },
10
+ { id: 3, name: 'Finish the project' },
11
+ ]
12
+
13
+ const todosRouter = {
14
+ list: publicProcedure.query(() => todos),
15
+ add: publicProcedure
16
+ .input(z.object({ name: z.string() }))
17
+ .mutation(({ input }) => {
18
+ const newTodo = { id: todos.length + 1, name: input.name }
19
+ todos.push(newTodo)
20
+ return newTodo
21
+ }),
22
+ } satisfies TRPCRouterRecord
23
+
24
+ export const trpcRouter = createTRPCRouter({
25
+ todos: todosRouter,
26
+ })
27
+ export type TRPCRouter = typeof trpcRouter
@@ -0,0 +1,50 @@
1
+ import { faker } from '@faker-js/faker'
2
+
3
+ export type Person = {
4
+ id: number
5
+ firstName: string
6
+ lastName: string
7
+ age: number
8
+ visits: number
9
+ progress: number
10
+ status: 'relationship' | 'complicated' | 'single'
11
+ subRows?: Person[]
12
+ }
13
+
14
+ const range = (len: number) => {
15
+ const arr: number[] = []
16
+ for (let i = 0; i < len; i++) {
17
+ arr.push(i)
18
+ }
19
+ return arr
20
+ }
21
+
22
+ const newPerson = (num: number): Person => {
23
+ return {
24
+ id: num,
25
+ firstName: faker.person.firstName(),
26
+ lastName: faker.person.lastName(),
27
+ age: faker.number.int(40),
28
+ visits: faker.number.int(1000),
29
+ progress: faker.number.int(100),
30
+ status: faker.helpers.shuffle<Person['status']>([
31
+ 'relationship',
32
+ 'complicated',
33
+ 'single',
34
+ ])[0]!,
35
+ }
36
+ }
37
+
38
+ export function makeData(...lens: number[]) {
39
+ const makeDataLevel = (depth = 0): Person[] => {
40
+ const len = lens[depth]!
41
+ return range(len).map((index): Person => {
42
+ return {
43
+ ...newPerson(index),
44
+ subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined,
45
+ }
46
+ })
47
+ }
48
+
49
+ return makeDataLevel()
50
+ }