├── .gitignore ├── .npmrc ├── pnpm-workspace.yaml ├── .husky └── pre-commit ├── playground ├── maximal_starter │ ├── .eslintrc.json │ ├── .prettierrc.json │ ├── .prettierignore │ ├── postcss.config.js │ ├── public │ │ ├── images │ │ │ ├── sideclub.jpg │ │ │ ├── screenshot.png │ │ │ ├── github-org-access.png │ │ │ ├── bg-circlegrid.svg │ │ │ ├── bg-circlegrid-dark.svg │ │ │ ├── bg-squaregrid.svg │ │ │ ├── bg-squaregrid-dark.svg │ │ │ ├── notifications_FILL0_wght400_GRAD0_opsz24.svg │ │ │ ├── letters │ │ │ │ ├── y.svg │ │ │ │ ├── l.svg │ │ │ │ ├── t.svg │ │ │ │ ├── v.svg │ │ │ │ ├── x.svg │ │ │ │ ├── i.svg │ │ │ │ ├── f.svg │ │ │ │ ├── j.svg │ │ │ │ ├── k.svg │ │ │ │ ├── c.svg │ │ │ │ ├── p.svg │ │ │ │ ├── d.svg │ │ │ │ ├── h.svg │ │ │ │ ├── u.svg │ │ │ │ ├── m.svg │ │ │ │ ├── n.svg │ │ │ │ ├── z.svg │ │ │ │ ├── e.svg │ │ │ │ ├── a.svg │ │ │ │ ├── g.svg │ │ │ │ ├── o.svg │ │ │ │ ├── r.svg │ │ │ │ ├── s.svg │ │ │ │ ├── b.svg │ │ │ │ ├── q.svg │ │ │ │ └── w.svg │ │ │ └── logo.svg │ │ ├── fonts │ │ │ ├── inter-roman.var.woff2 │ │ │ └── inter-italic.var.woff2 │ │ └── manifest.webmanifest │ ├── lib │ │ ├── classnames.ts │ │ ├── prisma.ts │ │ ├── types.ts │ │ ├── cloudinary.ts │ │ ├── form.ts │ │ ├── text.ts │ │ ├── trpc.ts │ │ ├── editor.ts │ │ └── auth.ts │ ├── pages │ │ ├── api │ │ │ ├── auth │ │ │ │ └── [...nextauth].ts │ │ │ ├── trpc │ │ │ │ └── [trpc].ts │ │ │ ├── sign-cloudinary.ts │ │ │ └── avatar.ts │ │ ├── _document.tsx │ │ ├── new.tsx │ │ ├── sign-in.tsx │ │ ├── index.tsx │ │ ├── _app.tsx │ │ └── project │ │ │ └── [id] │ │ │ └── edit.tsx │ ├── server │ │ ├── create-router.ts │ │ ├── create-protected-router.ts │ │ ├── routers │ │ │ ├── _app.ts │ │ │ ├── comment.ts │ │ │ ├── user.ts │ │ │ └── public.ts │ │ └── context.ts │ ├── next.config.js │ ├── next-env.d.ts │ ├── env │ │ ├── browser.ts │ │ └── server.ts │ ├── components │ │ ├── footer.tsx │ │ ├── html-view.tsx │ │ ├── banner.tsx │ │ ├── textarea.tsx │ │ ├── text-field.tsx │ │ ├── icon-button.tsx │ │ ├── button-link.tsx │ │ ├── owner-with-date.tsx │ │ ├── project-summary-skeleton.tsx │ │ ├── action-button.tsx │ │ ├── pagination.tsx │ │ ├── avatar.tsx │ │ ├── button.tsx │ │ ├── vote-button.tsx │ │ ├── project-form.tsx │ │ ├── menu.tsx │ │ ├── dialog.tsx │ │ ├── project-summary.tsx │ │ ├── search-dialog.tsx │ │ ├── markdown-editor.tsx │ │ └── layout.tsx │ ├── .env.example │ ├── .pscale │ │ └── cli-helper-scripts │ │ │ ├── authenticate-ps.sh │ │ │ ├── create-db-branch-dr-and-connection.sh │ │ │ ├── set-db-and-org-and-branch-name.sh │ │ │ ├── create-database.sh │ │ │ ├── wait-for-branch-readiness.sh │ │ │ ├── use-pscale-docker-image.sh │ │ │ ├── create-branch-connection-string.sh │ │ │ └── ps-create-helper-functions.sh │ ├── .gitignore │ ├── utils │ │ ├── context.ts │ │ └── reducer.ts │ ├── tsconfig.json │ ├── LICENSE │ ├── package.json │ ├── README.md │ ├── prisma │ │ └── schema.prisma │ ├── styles │ │ └── globals.css │ └── tailwind.config.js └── minimal_starter │ ├── .eslintrc.json │ ├── public │ └── favicon.ico │ ├── README.md │ ├── next-env.d.ts │ ├── utils │ ├── prisma.ts │ ├── trpc.ts │ └── reducer.ts │ ├── prisma │ └── schema.prisma │ ├── src │ ├── pages │ │ ├── api │ │ │ └── trpc │ │ │ │ └── [trpc].ts │ │ ├── _app.tsx │ │ └── index.tsx │ ├── server │ │ └── router │ │ │ ├── index.ts │ │ │ ├── context.ts │ │ │ └── example.ts │ └── styles │ │ └── globals.css │ ├── .gitignore │ ├── tsconfig.json │ └── package.json ├── .vscode ├── extensions.json └── settings.json ├── tsconfig.json ├── dprint.json ├── LICENSE ├── package.json ├── README.md └── src └── index.tsx /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | public-hoist-pattern[]=*types* 2 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - '.' 3 | - 'playground' 4 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | pnpm nano-staged 5 | -------------------------------------------------------------------------------- /playground/maximal_starter/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /playground/minimal_starter/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["next/core-web-vitals"] 3 | } 4 | -------------------------------------------------------------------------------- /playground/maximal_starter/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["dbaeumer.vscode-eslint", "dprint.dprint"] 3 | } 4 | -------------------------------------------------------------------------------- /playground/maximal_starter/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .next 3 | yarn.lock 4 | package-lock.json 5 | public -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.defaultFormatter": "dprint.dprint", 3 | "dprint.path": "node_modules/dprint/dprint" 4 | } 5 | -------------------------------------------------------------------------------- /playground/maximal_starter/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /playground/minimal_starter/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabriel-frattini/trpc-reducer/HEAD/playground/minimal_starter/public/favicon.ico -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/sideclub.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabriel-frattini/trpc-reducer/HEAD/playground/maximal_starter/public/images/sideclub.jpg -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabriel-frattini/trpc-reducer/HEAD/playground/maximal_starter/public/images/screenshot.png -------------------------------------------------------------------------------- /playground/minimal_starter/README.md: -------------------------------------------------------------------------------- 1 | # Create T3 App 2 | 3 | This is an app bootstrapped according to the [init.tips](https://init.tips) stack, also known as the T3-Stack. 4 | -------------------------------------------------------------------------------- /playground/maximal_starter/lib/classnames.ts: -------------------------------------------------------------------------------- 1 | export function classNames(...classes: (string | undefined | null | false)[]) { 2 | return classes.filter(Boolean).join(' ') 3 | } 4 | -------------------------------------------------------------------------------- /playground/maximal_starter/pages/api/auth/[...nextauth].ts: -------------------------------------------------------------------------------- 1 | import { authOptions } from '@/lib/auth' 2 | import NextAuth from 'next-auth' 3 | 4 | export default NextAuth(authOptions) 5 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/fonts/inter-roman.var.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabriel-frattini/trpc-reducer/HEAD/playground/maximal_starter/public/fonts/inter-roman.var.woff2 -------------------------------------------------------------------------------- /playground/maximal_starter/public/fonts/inter-italic.var.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabriel-frattini/trpc-reducer/HEAD/playground/maximal_starter/public/fonts/inter-italic.var.woff2 -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/github-org-access.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabriel-frattini/trpc-reducer/HEAD/playground/maximal_starter/public/images/github-org-access.png -------------------------------------------------------------------------------- /playground/maximal_starter/server/create-router.ts: -------------------------------------------------------------------------------- 1 | import * as trpc from '@trpc/server' 2 | import { Context } from './context' 3 | 4 | export function createRouter() { 5 | return trpc.router() 6 | } 7 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/bg-circlegrid.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/bg-circlegrid-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /playground/maximal_starter/next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | module.exports = { 3 | reactStrictMode: true, 4 | images: { 5 | domains: ['res.cloudinary.com', 'avatars.githubusercontent.com'], 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/bg-squaregrid.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/manifest.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "icons": [ 3 | { "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" }, 4 | { "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" } 5 | ] 6 | } -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/bg-squaregrid-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /playground/maximal_starter/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /playground/minimal_starter/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /playground/maximal_starter/env/browser.ts: -------------------------------------------------------------------------------- 1 | import { bool, envsafe } from 'envsafe' 2 | 3 | export const browserEnv = envsafe({ 4 | NEXT_PUBLIC_ENABLE_IMAGE_UPLOAD: bool({ 5 | input: process.env.NEXT_PUBLIC_ENABLE_IMAGE_UPLOAD, 6 | default: false, 7 | }), 8 | }) 9 | -------------------------------------------------------------------------------- /playground/maximal_starter/components/footer.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export function Footer() { 4 | return ( 5 |
6 | ) 7 | } 8 | -------------------------------------------------------------------------------- /playground/maximal_starter/lib/prisma.ts: -------------------------------------------------------------------------------- 1 | import { PrismaClient } from '@prisma/client' 2 | 3 | declare global { 4 | var prisma: PrismaClient | undefined 5 | } 6 | 7 | export const prisma = global.prisma || new PrismaClient() 8 | 9 | if (process.env.NODE_ENV !== 'production') global.prisma = prisma 10 | -------------------------------------------------------------------------------- /playground/minimal_starter/utils/prisma.ts: -------------------------------------------------------------------------------- 1 | import { PrismaClient } from '@prisma/client' 2 | 3 | declare global { 4 | var prisma: PrismaClient | undefined 5 | } 6 | 7 | export const prisma = global.prisma || new PrismaClient() 8 | 9 | if (process.env.NODE_ENV !== 'production') global.prisma = prisma 10 | -------------------------------------------------------------------------------- /playground/minimal_starter/utils/trpc.ts: -------------------------------------------------------------------------------- 1 | import { createReactQueryHooks } from '@trpc/react' 2 | import { createTrpcReducer } from 'trpc-reducer' 3 | import type { AppRouter } from '../src/server/router' 4 | 5 | export const trpc = createReactQueryHooks() 6 | export const trpcReducer = createTrpcReducer(trpc) 7 | -------------------------------------------------------------------------------- /playground/maximal_starter/.env.example: -------------------------------------------------------------------------------- 1 | DATABASE_URL= 2 | PORT=3000 3 | NODE_ENV=development 4 | 5 | AUTH_PROVIDER=github 6 | GITHUB_ID= 7 | GITHUB_SECRET= 8 | GITHUB_ALLOWED_ORG= 9 | 10 | NEXTAUTH_SECRET=secret 11 | NEXT_PUBLIC_ENABLE_IMAGE_UPLOAD=true 12 | 13 | CLOUDINARY_CLOUD_NAME= 14 | CLOUDINARY_API_KEY= 15 | CLOUDINARY_API_SECRET= 16 | 17 | -------------------------------------------------------------------------------- /playground/maximal_starter/lib/types.ts: -------------------------------------------------------------------------------- 1 | import { User } from '@prisma/client' 2 | import type { NextPage } from 'next' 3 | import * as React from 'react' 4 | 5 | export type NextPageWithAuthAndLayout = NextPage & { 6 | auth?: boolean 7 | getLayout?: (page: React.ReactElement) => React.ReactNode 8 | } 9 | 10 | export type Owner = Pick 11 | -------------------------------------------------------------------------------- /playground/minimal_starter/prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | // This is your Prisma schema file, 2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 | 4 | generator client { 5 | provider = "prisma-client-js" 6 | } 7 | 8 | datasource db { 9 | provider = "sqlite" 10 | url = "file:./dev.db" 11 | } 12 | 13 | model User { 14 | id String @id 15 | name String 16 | } -------------------------------------------------------------------------------- /playground/maximal_starter/components/html-view.tsx: -------------------------------------------------------------------------------- 1 | import { classNames } from '@/lib/classnames' 2 | 3 | type HtmlViewProps = { 4 | html: string 5 | className?: string 6 | } 7 | 8 | export function HtmlView({ html, className }: HtmlViewProps) { 9 | return ( 10 |
14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /playground/minimal_starter/src/pages/api/trpc/[trpc].ts: -------------------------------------------------------------------------------- 1 | // src/pages/api/trpc/[trpc].ts 2 | import { createNextApiHandler } from "@trpc/server/adapters/next"; 3 | import { appRouter } from "../../../server/router"; 4 | import { createContext } from "../../../server/router/context"; 5 | 6 | // export API handler 7 | export default createNextApiHandler({ 8 | router: appRouter, 9 | createContext: createContext, 10 | }); 11 | -------------------------------------------------------------------------------- /playground/minimal_starter/src/server/router/index.ts: -------------------------------------------------------------------------------- 1 | // src/server/router/index.ts 2 | import superjson from 'superjson' 3 | import { createRouter } from './context' 4 | 5 | import { exampleRouter } from './example' 6 | 7 | export const appRouter = createRouter() 8 | .transformer(superjson) 9 | .merge('example.', exampleRouter) 10 | 11 | // export type definition of API 12 | export type AppRouter = typeof appRouter 13 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/notifications_FILL0_wght400_GRAD0_opsz24.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /playground/maximal_starter/.pscale/cli-helper-scripts/authenticate-ps.sh: -------------------------------------------------------------------------------- 1 | # if PLANETSCALE_SERVICE_TOKEN is not set, use pscale auth login 2 | if [ -z "$PLANETSCALE_SERVICE_TOKEN" ]; then 3 | echo "Going to authenticate PlanetScale CLI, please follow the link displayed in your browser and confirm ..." 4 | pscale auth login 5 | # if command failed, exit 6 | if [ $? -ne 0 ]; then 7 | echo "pscale auth login failed, please try again" 8 | exit 1 9 | fi 10 | fi 11 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "strict": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "noEmit": true, 11 | "isolatedModules": true, 12 | "jsx": "preserve", 13 | "types": ["node"], 14 | "baseUrl": ".", 15 | "lib": ["dom", "esnext"] 16 | }, 17 | "include": ["src"], 18 | "exclude": ["node_modules"] 19 | } 20 | -------------------------------------------------------------------------------- /playground/maximal_starter/components/banner.tsx: -------------------------------------------------------------------------------- 1 | import { classNames } from '@/lib/classnames' 2 | import * as React from 'react' 3 | 4 | type BannerProps = { 5 | children: React.ReactNode 6 | className?: string 7 | } 8 | 9 | export function Banner({ children, className }: BannerProps) { 10 | return ( 11 |
17 | {children} 18 |
19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /playground/maximal_starter/pages/api/trpc/[trpc].ts: -------------------------------------------------------------------------------- 1 | import { createContext } from '@/server/context' 2 | import { appRouter } from '@/server/routers/_app' 3 | import * as trpcNext from '@trpc/server/adapters/next' 4 | 5 | export default trpcNext.createNextApiHandler({ 6 | router: appRouter, 7 | createContext, 8 | onError({ error }) { 9 | if (error.code === 'INTERNAL_SERVER_ERROR') { 10 | // send to bug reporting 11 | console.error('Something went wrong', error) 12 | } 13 | }, 14 | batching: { 15 | enabled: true, 16 | }, 17 | }) 18 | -------------------------------------------------------------------------------- /playground/maximal_starter/server/create-protected-router.ts: -------------------------------------------------------------------------------- 1 | import * as trpc from '@trpc/server' 2 | import { Context } from './context' 3 | 4 | export function createProtectedRouter() { 5 | return trpc.router().middleware(({ ctx, next }) => { 6 | if (!ctx.session) { 7 | throw new trpc.TRPCError({ code: 'UNAUTHORIZED' }) 8 | } 9 | 10 | const isUserAdmin = ctx.session.user.role === 'ADMIN' 11 | 12 | return next({ 13 | ctx: { 14 | ...ctx, 15 | session: ctx.session, 16 | isUserAdmin, 17 | }, 18 | }) 19 | }) 20 | } 21 | -------------------------------------------------------------------------------- /playground/maximal_starter/server/routers/_app.ts: -------------------------------------------------------------------------------- 1 | import superjson from 'superjson' 2 | import { createRouter } from '../create-router' 3 | import { commentRouter } from './comment' 4 | import { projectRouter } from './project' 5 | import { publicRouter } from './public' 6 | import { userRouter } from './user' 7 | 8 | export const appRouter = createRouter() 9 | .transformer(superjson) 10 | .merge('project.', projectRouter) 11 | .merge('comment.', commentRouter) 12 | .merge('user.', userRouter) 13 | .merge('public.', publicRouter) 14 | 15 | export type AppRouter = typeof appRouter 16 | -------------------------------------------------------------------------------- /playground/minimal_starter/src/server/router/context.ts: -------------------------------------------------------------------------------- 1 | // src/server/router/context.ts 2 | import * as trpc from '@trpc/server' 3 | import * as trpcNext from '@trpc/server/adapters/next' 4 | import { prisma } from '../../../utils/prisma' 5 | 6 | export const createContext = (opts?: trpcNext.CreateNextContextOptions) => { 7 | const req = opts?.req 8 | const res = opts?.res 9 | 10 | return { 11 | req, 12 | res, 13 | prisma, 14 | } 15 | } 16 | 17 | type Context = trpc.inferAsyncReturnType 18 | 19 | export const createRouter = () => trpc.router() 20 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/letters/y.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /playground/maximal_starter/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env 29 | .env.local 30 | .env.development.local 31 | .env.test.local 32 | .env.production.local 33 | 34 | # vercel 35 | .vercel 36 | 37 | # typescript 38 | *.tsbuildinfo 39 | -------------------------------------------------------------------------------- /playground/minimal_starter/utils/reducer.ts: -------------------------------------------------------------------------------- 1 | import { ReducerActions, ReducerOutput } from 'trpc-reducer' 2 | import { AppRouter } from '../src/server/router' 3 | 4 | export function myReducer( 5 | state: any, 6 | action: ReducerActions, 7 | ): ReducerOutput { 8 | switch (action.type[0]) { 9 | case 'example.user.create': 10 | return { 11 | users: [...state.users, action.payload], 12 | } 13 | 14 | case 'example.user.delete': 15 | return { 16 | users: state.users.filter((user: any) => user.id !== action.payload.id), 17 | } 18 | default: 19 | return state 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /playground/maximal_starter/server/context.ts: -------------------------------------------------------------------------------- 1 | import { authOptions } from '@/lib/auth' 2 | import { prisma } from '@/lib/prisma' 3 | import * as trpc from '@trpc/server' 4 | import * as trpcNext from '@trpc/server/adapters/next' 5 | import { unstable_getServerSession as getServerSession } from 'next-auth/next' 6 | 7 | export const createContext = async ({ 8 | req, 9 | res, 10 | }: trpcNext.CreateNextContextOptions) => { 11 | const session = await getServerSession(req, res, authOptions) 12 | 13 | return { 14 | req, 15 | res, 16 | prisma, 17 | session, 18 | } 19 | } 20 | 21 | export type Context = trpc.inferAsyncReturnType 22 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/letters/l.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /playground/maximal_starter/utils/context.ts: -------------------------------------------------------------------------------- 1 | import { TRPCClient } from '@trpc/client' 2 | import { AnyRouter, inferHandlerInput, inferProcedureOutput } from '@trpc/server' 3 | import { createContext } from 'react' 4 | 5 | export interface TRPCContextState { 6 | client: TRPCClient 7 | mutate< 8 | TPath extends keyof TRouter['_def']['queries'] & string, 9 | TProcedure extends TRouter['_def']['queries'][TPath], 10 | TOutput extends inferProcedureOutput, 11 | >( 12 | pathAndInput: [path: TPath, ...args: inferHandlerInput], 13 | ): Promise 14 | } 15 | 16 | export const TRPCContext = createContext(null as any) 17 | -------------------------------------------------------------------------------- /playground/maximal_starter/.pscale/cli-helper-scripts/create-db-branch-dr-and-connection.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . use-pscale-docker-image.sh 4 | . wait-for-branch-readiness.sh 5 | 6 | . authenticate-ps.sh 7 | 8 | BRANCH_NAME="$1" 9 | DDL_STATEMENTS="$2" 10 | 11 | . set-db-and-org-and-branch-name.sh 12 | 13 | . ps-create-helper-functions.sh 14 | create-db-branch "$DB_NAME" "$BRANCH_NAME" "$ORG_NAME" "recreate" 15 | create-schema-change "$DB_NAME" "$BRANCH_NAME" "$ORG_NAME" "$DDL_STATEMENTS" 16 | create-deploy-request "$DB_NAME" "$BRANCH_NAME" "$ORG_NAME" 17 | 18 | 19 | . create-branch-connection-string.sh 20 | create-branch-connection-string "$DB_NAME" "$BRANCH_NAME" "$ORG_NAME" "creds-${BRANCH_NAME}" "sharesecret" -------------------------------------------------------------------------------- /playground/minimal_starter/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | package-lock.json 8 | 9 | # testing 10 | /coverage 11 | 12 | # database 13 | /prisma/db.sqlite 14 | /prisma/dev.db 15 | /prisma/db.sqlite-journal 16 | /prisma/migrations/* 17 | 18 | 19 | # next.js 20 | /.next/ 21 | /out/ 22 | 23 | # production 24 | /build 25 | 26 | # misc 27 | .DS_Store 28 | *.pem 29 | 30 | # debug 31 | npm-debug.log* 32 | yarn-debug.log* 33 | yarn-error.log* 34 | .pnpm-debug.log* 35 | 36 | # local env files 37 | .env 38 | .env*.local 39 | 40 | # vercel 41 | .vercel 42 | 43 | # typescript 44 | *.tsbuildinfo 45 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/letters/t.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /playground/minimal_starter/src/styles/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 4 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 5 | } 6 | 7 | a { 8 | color: inherit; 9 | text-decoration: none; 10 | } 11 | 12 | * { 13 | box-sizing: border-box; 14 | padding: 0; 15 | } 16 | 17 | main { 18 | max-width: 325px; 19 | margin: auto; 20 | } 21 | 22 | h1 { 23 | text-align: center; 24 | margin-top: 100px; 25 | } 26 | 27 | form { 28 | display: flex; 29 | justify-content: space-between; 30 | margin-top: 20px; 31 | } 32 | 33 | li { 34 | display: flex; 35 | justify-content: space-between; 36 | margin-bottom: 10px; 37 | } 38 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/letters/v.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/letters/x.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/letters/i.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /playground/minimal_starter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true, 17 | "noUncheckedIndexedAccess": true 18 | }, 19 | "include": [ 20 | "next-env.d.ts", 21 | "next-auth.d.ts", 22 | "**/*.ts", 23 | "**/*.tsx", 24 | "**/*.js" 25 | ], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /dprint.json: -------------------------------------------------------------------------------- 1 | { 2 | "incremental": true, 3 | "indentWidth": 2, 4 | "typescript": { 5 | "quoteStyle": "preferSingle", 6 | "semiColons": "asi" 7 | }, 8 | "prettier": { 9 | "singleQuote": true, 10 | "associations": [ 11 | "**/*.yaml", 12 | "**/*.json5" 13 | ] 14 | }, 15 | "includes": ["**/*.{ts,tsx,js,jsx,cjs,mjs,json,json5,md,yaml}"], 16 | "excludes": ["**/node_modules", "pnpm-lock.yaml", "dist", ".next"], 17 | "plugins": [ 18 | "https://plugins.dprint.dev/typescript-0.68.0.wasm", 19 | "https://plugins.dprint.dev/json-0.15.1.wasm", 20 | "https://plugins.dprint.dev/markdown-0.13.1.wasm", 21 | "https://plugins.dprint.dev/prettier-0.7.0.json@4e846f43b32981258cef5095b3d732522947592e090ef52333801f9d6e8adb33" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/letters/f.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/letters/j.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/letters/k.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/letters/c.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /playground/maximal_starter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true, 17 | "noUnusedParameters": false, 18 | "noUnusedLocals": false, 19 | "baseUrl": ".", 20 | "paths": { 21 | "@/components/*": ["components/*"], 22 | "@/lib/*": ["lib/*"], 23 | "@/server/*": ["server/*"], 24 | "@/env/*": ["env/*"] 25 | } 26 | }, 27 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 28 | "exclude": ["node_modules"] 29 | } 30 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/letters/p.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/letters/d.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/letters/h.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/letters/u.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /playground/minimal_starter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-t3-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@prisma/client": "^4.1.0", 13 | "@trpc/client": "^9.26.2", 14 | "@trpc/next": "^9.26.2", 15 | "@trpc/react": "^9.26.2", 16 | "@trpc/server": "^9.26.2", 17 | "next": "12.2.1", 18 | "react": "18.2.0", 19 | "react-dom": "18.2.0", 20 | "react-query": "^3.39.2", 21 | "superjson": "^1.9.1", 22 | "trpc-reducer": "^0.2.8", 23 | "zod": "^3.17.3" 24 | }, 25 | "devDependencies": { 26 | "@types/node": "18.0.0", 27 | "@types/react": "18.0.14", 28 | "@types/react-dom": "18.0.5", 29 | "eslint": "8.18.0", 30 | "eslint-config-next": "12.2.1", 31 | "ts-loader": "^9.3.1", 32 | "typescript": "^4.7.4" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/letters/m.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/letters/n.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/letters/z.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /playground/maximal_starter/public/images/letters/e.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /playground/maximal_starter/components/textarea.tsx: -------------------------------------------------------------------------------- 1 | import { classNames } from '@/lib/classnames' 2 | import * as React from 'react' 3 | 4 | export type TextareaOwnProps = { 5 | label?: string 6 | } 7 | 8 | type TextareaProps = TextareaOwnProps & 9 | React.ComponentPropsWithoutRef<'textarea'> 10 | 11 | export const Textarea = React.forwardRef( 12 | ({ label, id, name, className, ...rest }, forwardedRef) => { 13 | return ( 14 |
15 | {label && ( 16 | 19 | )} 20 |