create-tnt-stack 0.5.2-beta.4072da9 → 0.5.2
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.
package/dist/index.js
CHANGED
@@ -51,7 +51,7 @@ Using: ${I.cyan.bold(s)}
|
|
51
51
|
`).start();if(O.existsSync(a))if(O.readdirSync(a).length===0)e!=="."&&n.info(`${I.cyan.bold(e)} exists but is empty, continuing...
|
52
52
|
`);else{n.stopAndPersist();let l=await it({message:`${I.redBright.bold("Warning:")} ${I.cyan.bold(e)} already exists and isn't empty. How would you like to proceed?`,choices:[{value:"abort",name:"Abort installation (recommended)"},{value:"clear",name:"Clear the directory and continue installation"},{value:"overwrite",name:"Continue installation and overwrite conflicting files"}],default:"abort"});l==="abort"&&(n.fail("Aborting installation..."),process.exit(1)),await ot({message:`Are you sure you want to ${l==="clear"?"clear the directory":"overwrite conflicting files"}`,default:!1})||(n.fail("Aborting installation..."),process.exit(1)),l==="clear"&&(n.info(`Emptying ${I.cyan.bold(e)} and creating tnt app...
|
53
53
|
`),O.emptyDirSync(a))}n.start(),O.copySync(t,a),O.renameSync(W.join(a,"_gitignore"),W.join(a,".gitignore"));let i=e==="."?"App":I.cyan.bold(e);n.succeed(`${i} ${I.green.bold("scaffolded successfully!")}
|
54
|
-
`)}import v from"path";import B from"fs-extra";function Pe({packages:e,projectDir:a}){let s=v.join(c,"template/packages/src/app/layout"),o=e.payload.inUse,n=v.join(s,"base.tsx"),i=v.join(a,`src/app/${o?"(frontend)":""}/layout.tsx`);B.copySync(n,i)}function _e({packages:e,projectDir:a}){let s=v.join(c,"template/packages/src/app/page"),o=e.payload.inUse,t=e.authjs.inUse,n=e.prisma.inUse,i="base.tsx";o&&(i="with-payload.tsx"),t&&(i="with-authjs.tsx"),n&&(i="with-prisma.tsx");let l=v.join(s,i),d=v.join(a,`src/app/${o?"(frontend)":""}/page.tsx`);B.copySync(l,d)}function Se({packages:e,projectDir:a}){let s=v.join(c,"template/packages/src/app/globals"),o=e.payload.inUse,n=v.join(s,"base.css"),i=v.join(a,`src/app/${o?"(frontend)":""}/globals.css`);B.copySync(n,i)}async function xe({projectName:e,scopedAppName:a,packages:s,noInstall:o,databaseProvider:t}){let n=h(),i=lt.resolve(process.cwd(),e);return await we({projectName:e,projectDir:i,pkgManager:n,scopedAppName:a,noInstall:o,databaseProvider:t}),ke({projectName:e,scopedAppName:a,projectDir:i,pkgManager:n,packages:s,noInstall:o,databaseProvider:t}),Pe({packages:s,projectDir:i}),_e({packages:s,projectDir:i}),Se({packages:s,projectDir:i}),i}import{execSync as z}from"child_process";import V from"path";import{confirm as Ie}from"@inquirer/prompts";import T from"chalk";import{execa as D}from"execa";import Ae from"fs-extra";import pt from"ora";function ct(e){try{return z("git --version",{cwd:e}),!0}catch{return!1}}function K(e){return Ae.existsSync(V.join(e,".git"))}async function H(e){try{return await D("git",["rev-parse","--is-inside-work-tree"],{cwd:e,stdout:"ignore"}),!0}catch{return!1}}function mt(){let a=z("git --version").toString().trim().split(" ")[2],s=a?.split(".")[0],o=a?.split(".")[1];return{major:Number(s),minor:Number(o)}}function dt(){return z("git config --global init.defaultBranch || echo main").toString().trim()}async function je(e){if(r.info("Initializing Git..."),!ct(e)){r.warn("Git is not installed. Skipping Git initialization.");return}let a=pt(`Creating a new git repo...
|
54
|
+
`)}import v from"path";import B from"fs-extra";function Pe({packages:e,projectDir:a}){let s=v.join(c,"template/packages/src/app/layout"),o=e.payload.inUse,n=v.join(s,"base.tsx"),i=v.join(a,`src/app/${o?"(frontend)":""}/layout.tsx`);B.copySync(n,i)}function _e({packages:e,projectDir:a}){let s=v.join(c,"template/packages/src/app/page"),o=e.payload.inUse,t=e.authjs.inUse,n=e.prisma.inUse,i="base.tsx";o&&(i="with-payload.tsx"),t&&(i="with-authjs.tsx"),n&&(i="with-prisma.tsx"),t&&n&&(i="with-authjs-prisma.tsx");let l=v.join(s,i),d=v.join(a,`src/app/${o?"(frontend)":""}/page.tsx`);B.copySync(l,d)}function Se({packages:e,projectDir:a}){let s=v.join(c,"template/packages/src/app/globals"),o=e.payload.inUse,n=v.join(s,"base.css"),i=v.join(a,`src/app/${o?"(frontend)":""}/globals.css`);B.copySync(n,i)}async function xe({projectName:e,scopedAppName:a,packages:s,noInstall:o,databaseProvider:t}){let n=h(),i=lt.resolve(process.cwd(),e);return await we({projectName:e,projectDir:i,pkgManager:n,scopedAppName:a,noInstall:o,databaseProvider:t}),ke({projectName:e,scopedAppName:a,projectDir:i,pkgManager:n,packages:s,noInstall:o,databaseProvider:t}),Pe({packages:s,projectDir:i}),_e({packages:s,projectDir:i}),Se({packages:s,projectDir:i}),i}import{execSync as z}from"child_process";import V from"path";import{confirm as Ie}from"@inquirer/prompts";import T from"chalk";import{execa as D}from"execa";import Ae from"fs-extra";import pt from"ora";function ct(e){try{return z("git --version",{cwd:e}),!0}catch{return!1}}function K(e){return Ae.existsSync(V.join(e,".git"))}async function H(e){try{return await D("git",["rev-parse","--is-inside-work-tree"],{cwd:e,stdout:"ignore"}),!0}catch{return!1}}function mt(){let a=z("git --version").toString().trim().split(" ")[2],s=a?.split(".")[0],o=a?.split(".")[1];return{major:Number(s),minor:Number(o)}}function dt(){return z("git config --global init.defaultBranch || echo main").toString().trim()}async function je(e){if(r.info("Initializing Git..."),!ct(e)){r.warn("Git is not installed. Skipping Git initialization.");return}let a=pt(`Creating a new git repo...
|
55
55
|
`).start(),s=K(e),o=await H(e),t=V.parse(e).name;if(o&&s){if(a.stop(),!await Ie({message:`${T.redBright.bold("Warning:")} Git is already initialized in "${t}". Initializing a new git repository would delete the previous history. Would you like to continue anyways?`,default:!1})){a.info("Skipping Git initialization.");return}Ae.removeSync(V.join(e,".git"))}else if(o&&!s&&(a.stop(),!await Ie({message:`${T.redBright.bold("Warning:")} "${t}" is already in a git worktree. Would you still like to initialize a new git repository in this directory?`,default:!1}))){a.info("Skipping Git initialization.");return}try{let n=dt(),{major:i,minor:l}=mt();i<2||i==2&&l<28?(await D("git",["init"],{cwd:e}),await D("git",["symbolic-ref","HEAD",`refs/heads/${n}`],{cwd:e})):await D("git",["init",`--initial-branch=${n}`],{cwd:e}),await D("git",["add","."],{cwd:e}),a.succeed(`${T.green("Successfully initialized and staged")} ${T.green.bold("git")}
|
56
56
|
`)}catch{a.fail(`${T.bold.red("Failed:")} could not initialize git. Update git to the latest version!
|
57
57
|
`)}}import ft from"chalk";import{execa as Ce}from"execa";import Oe from"ora";var Y=async(e,a,s)=>{let{onDataHandle:o,args:t=["install"],stdout:n="pipe"}=s,i=Oe(`Running ${a} install...`).start(),l=Ce(a,t,{cwd:e,stdout:n});return await new Promise((d,g)=>{o&&l.stdout?.on("data",o(i)),l.on("error",u=>g(u)),l.on("close",()=>d())}),i},gt=async(e,a)=>{switch(e){case"npm":return await Ce(e,["install"],{cwd:a,stderr:"inherit"}),null;case"pnpm":return Y(a,e,{onDataHandle:s=>o=>{let t=o.toString();t.includes("Progress")&&(s.text=t.includes("|")?t.split(" | ")[1]??"":t)}});case"yarn":return Y(a,e,{onDataHandle:s=>o=>{s.text=o.toString()}});case"bun":return Y(a,e,{stdout:"ignore"})}},Te=async({projectDir:e})=>{r.info("Installing dependencies...");let a=h();(await gt(a,e)??Oe()).succeed(ft.green(`Successfully installed dependencies!
|
package/package.json
CHANGED
@@ -1,89 +1,89 @@
|
|
1
1
|
{
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
2
|
+
"name": "create-tnt-stack",
|
3
|
+
"version": "0.5.2",
|
4
|
+
"description": "Create web application with the TNT-Powered stack",
|
5
|
+
"license": "MIT",
|
6
|
+
"repository": {
|
7
|
+
"type": "git",
|
8
|
+
"url": "https://github.com/slickyeet/create-tnt-stack",
|
9
|
+
"directory": "cli"
|
10
|
+
},
|
11
|
+
"keywords": [
|
12
|
+
"create-tnt-stack",
|
13
|
+
"tnt-stack",
|
14
|
+
"typescript",
|
15
|
+
"next.js",
|
16
|
+
"tailwind"
|
17
|
+
],
|
18
|
+
"type": "module",
|
19
|
+
"exports": "./dist/index.js",
|
20
|
+
"bin": {
|
21
|
+
"create-tnt-stack": "./dist/index.js"
|
22
|
+
},
|
23
|
+
"files": [
|
24
|
+
"dist",
|
25
|
+
"template",
|
26
|
+
"README.md",
|
27
|
+
"LICENSE",
|
28
|
+
"package.json"
|
29
|
+
],
|
30
|
+
"engines": {
|
31
|
+
"node": ">=18"
|
32
|
+
},
|
33
|
+
"scripts": {
|
34
|
+
"dev": "tsup --watch",
|
35
|
+
"build": "tsup",
|
36
|
+
"start": "node dist/index.js",
|
37
|
+
"format": "prettier '**/*.{cjs,mjs,ts,tsx,md,json}' --ignore-path ../.gitignore --ignore-unknown --no-error-on-unmatched-pattern --write",
|
38
|
+
"format:check": "prettier '**/*.{cjs,mjs,ts,tsx,md,json}' --ignore-path ../.gitignore --ignore-unknown --no-error-on-unmatched-pattern --check",
|
39
|
+
"typecheck": "tsc",
|
40
|
+
"clean": "rm -rf dist .turbo node_modules",
|
41
|
+
"link": "bun run build && npm link",
|
42
|
+
"release": "changeset version",
|
43
|
+
"pub:beta": "bun run build && npm publish --tag beta",
|
44
|
+
"pub:release": "bun run build && npm publish"
|
45
|
+
},
|
46
|
+
"dependencies": {
|
47
|
+
"@inquirer/prompts": "^7.4.0",
|
48
|
+
"chalk": "^5.4.1",
|
49
|
+
"commander": "^13.1.0",
|
50
|
+
"execa": "^9.5.2",
|
51
|
+
"fs-extra": "^11.3.0",
|
52
|
+
"gradient-string": "^3.0.0",
|
53
|
+
"ora": "^8.2.0",
|
54
|
+
"sort-package-json": "^3.0.0"
|
55
|
+
},
|
56
|
+
"devDependencies": {
|
57
|
+
"@auth/prisma-adapter": "^2.8.0",
|
58
|
+
"@eslint/eslintrc": "^3.3.1",
|
59
|
+
"@ianvs/prettier-plugin-sort-imports": "^4.4.1",
|
60
|
+
"@payloadcms/db-sqlite": "^3.33.0",
|
61
|
+
"@payloadcms/db-vercel-postgres": "^3.33.0",
|
62
|
+
"@payloadcms/next": "^3.33.0",
|
63
|
+
"@payloadcms/payload-cloud": "^3.33.0",
|
64
|
+
"@payloadcms/richtext-lexical": "^3.33.0",
|
65
|
+
"@prisma/client": "^6.5.0",
|
66
|
+
"@t3-oss/env-nextjs": "^0.12.0",
|
67
|
+
"@types/fs-extra": "^11.0.4",
|
68
|
+
"@types/node": "^22",
|
69
|
+
"@types/react": "^19",
|
70
|
+
"@types/react-dom": "^19",
|
71
|
+
"eslint": "^9.22.0",
|
72
|
+
"eslint-config-next": "^15.2.4",
|
73
|
+
"graphql": "^16.10.0",
|
74
|
+
"next": "^15.2.4",
|
75
|
+
"next-auth": "^5.0.0-beta.25",
|
76
|
+
"payload": "^3.33.0",
|
77
|
+
"prettier": "^3.5.3",
|
78
|
+
"prettier-plugin-tailwindcss": "^0.6.11",
|
79
|
+
"prisma": "^6.5.0",
|
80
|
+
"react": "^19.0.0",
|
81
|
+
"react-dom": "^19.0.0",
|
82
|
+
"sharp": "^0.34.1",
|
83
|
+
"tailwindcss": "^4.0.17",
|
84
|
+
"tsup": "^8.4.0",
|
85
|
+
"type-fest": "^4.37.0",
|
86
|
+
"typescript": "^5.8.2",
|
87
|
+
"zod": "^3.24.2"
|
88
|
+
}
|
89
89
|
}
|
@@ -15,14 +15,15 @@ datasource db {
|
|
15
15
|
}
|
16
16
|
|
17
17
|
model Post {
|
18
|
-
id
|
19
|
-
name
|
20
|
-
createdAt DateTime @default(now())
|
21
|
-
updatedAt DateTime @updatedAt
|
18
|
+
id String @id @default(cuid())
|
19
|
+
name String
|
22
20
|
|
23
21
|
createdBy User @relation(fields: [createdById], references: [id])
|
24
22
|
createdById String
|
25
23
|
|
24
|
+
createdAt DateTime @default(now())
|
25
|
+
updatedAt DateTime @updatedAt
|
26
|
+
|
26
27
|
@@index([name])
|
27
28
|
}
|
28
29
|
|
@@ -0,0 +1,221 @@
|
|
1
|
+
import { fileURLToPath } from "url"
|
2
|
+
import { revalidatePath } from "next/cache"
|
3
|
+
|
4
|
+
import { auth, signIn, signOut } from "@/server/auth"
|
5
|
+
import { db } from "@/server/db"
|
6
|
+
|
7
|
+
export default async function HomePage() {
|
8
|
+
const session = await auth()
|
9
|
+
const user = session?.user
|
10
|
+
|
11
|
+
const posts = await db.post.findMany()
|
12
|
+
|
13
|
+
const fileURL = `vscode://file/${fileURLToPath(import.meta.url)}`
|
14
|
+
|
15
|
+
return (
|
16
|
+
<main className="mx-auto flex h-screen max-w-5xl flex-col items-center justify-between overflow-hidden p-6 sm:p-[45px]">
|
17
|
+
<header className="ml-auto">
|
18
|
+
{user ? (
|
19
|
+
<button
|
20
|
+
onClick={async () => {
|
21
|
+
"use server"
|
22
|
+
await signOut()
|
23
|
+
}}
|
24
|
+
className="cursor-pointer rounded-md bg-rose-400 px-4 py-2"
|
25
|
+
>
|
26
|
+
Sign Out
|
27
|
+
</button>
|
28
|
+
) : (
|
29
|
+
<button
|
30
|
+
onClick={async () => {
|
31
|
+
"use server"
|
32
|
+
await signIn("discord")
|
33
|
+
}}
|
34
|
+
className="cursor-pointer rounded-md bg-purple-400 px-4 py-2"
|
35
|
+
>
|
36
|
+
Sign In
|
37
|
+
</button>
|
38
|
+
)}
|
39
|
+
</header>
|
40
|
+
|
41
|
+
<div className="flex grow flex-col items-center justify-center">
|
42
|
+
{/* Logo */}
|
43
|
+
<picture className="relative">
|
44
|
+
<div className="absolute inset-0 animate-pulse rounded-xl bg-gradient-to-r from-purple-500 to-cyan-500 opacity-20 blur-xl dark:from-purple-800 dark:to-cyan-800" />
|
45
|
+
<source srcSet="https://github.com/SlickYeet/create-tnt-stack/blob/main/docs/public/logo.light.png?raw=true" />
|
46
|
+
<img
|
47
|
+
src="https://github.com/SlickYeet/create-tnt-stack/blob/main/docs/public/logo.light.png?raw=true"
|
48
|
+
alt="Logo"
|
49
|
+
width={65}
|
50
|
+
height={65}
|
51
|
+
className="block h-auto max-w-full"
|
52
|
+
/>
|
53
|
+
</picture>
|
54
|
+
|
55
|
+
<h1 className="mt-6 bg-gradient-to-r from-purple-500 to-cyan-500 bg-clip-text text-center text-4xl leading-10 text-transparent sm:text-5xl sm:leading-14 md:text-6xl md:leading-20 lg:mt-10 lg:text-7xl lg:font-bold">
|
56
|
+
TNT-Powered Next.js App
|
57
|
+
</h1>
|
58
|
+
<p className="mt-4 text-center text-lg text-neutral-700 md:text-xl lg:mt-6 dark:text-neutral-300">
|
59
|
+
Build modern web applications with today's most popular tools
|
60
|
+
</p>
|
61
|
+
|
62
|
+
<div className="mt-12 flex items-center gap-3">
|
63
|
+
<a
|
64
|
+
href="https://create.tntstack.org"
|
65
|
+
target="_blank"
|
66
|
+
rel="noopener noreferrer"
|
67
|
+
className="flex items-center rounded-md border border-white px-2 py-1 outline-none focus:opacity-80 active:opacity-70"
|
68
|
+
>
|
69
|
+
Website
|
70
|
+
<svg
|
71
|
+
xmlns="http://www.w3.org/2000/svg"
|
72
|
+
viewBox="0 0 24 24"
|
73
|
+
strokeLinecap="round"
|
74
|
+
strokeLinejoin="round"
|
75
|
+
className="mb-1.5 size-4 fill-none stroke-current stroke-2"
|
76
|
+
>
|
77
|
+
<path d="M7 7h10v10" />
|
78
|
+
<path d="M7 17 17 7" />
|
79
|
+
</svg>
|
80
|
+
</a>
|
81
|
+
<a
|
82
|
+
href="https://create.tntstack.org/introduction"
|
83
|
+
target="_blank"
|
84
|
+
rel="noopener noreferrer"
|
85
|
+
className="flex items-center rounded-md border border-white px-2 py-1 outline-none focus:opacity-80 active:opacity-70"
|
86
|
+
>
|
87
|
+
Docs
|
88
|
+
<svg
|
89
|
+
xmlns="http://www.w3.org/2000/svg"
|
90
|
+
viewBox="0 0 24 24"
|
91
|
+
strokeLinecap="round"
|
92
|
+
strokeLinejoin="round"
|
93
|
+
className="mb-1.5 size-4 fill-none stroke-current stroke-2"
|
94
|
+
>
|
95
|
+
<path d="M7 7h10v10" />
|
96
|
+
<path d="M7 17 17 7" />
|
97
|
+
</svg>
|
98
|
+
</a>
|
99
|
+
<a
|
100
|
+
href="https://github.com/SlickYeet/create-tnt-stack"
|
101
|
+
target="_blank"
|
102
|
+
rel="noopener noreferrer"
|
103
|
+
className="flex items-center rounded-md border border-white px-2 py-1 outline-none focus:opacity-80 active:opacity-70"
|
104
|
+
>
|
105
|
+
GitHub
|
106
|
+
<svg
|
107
|
+
xmlns="http://www.w3.org/2000/svg"
|
108
|
+
viewBox="0 0 24 24"
|
109
|
+
strokeLinecap="round"
|
110
|
+
strokeLinejoin="round"
|
111
|
+
className="mb-1.5 size-4 fill-none stroke-current stroke-2"
|
112
|
+
>
|
113
|
+
<path d="M7 7h10v10" />
|
114
|
+
<path d="M7 17 17 7" />
|
115
|
+
</svg>
|
116
|
+
</a>
|
117
|
+
</div>
|
118
|
+
|
119
|
+
<div className="mt-12 flex flex-col items-center gap-3">
|
120
|
+
<div className="mb-4">
|
121
|
+
<h1 className="mb-4 text-center">
|
122
|
+
<span className="text-2xl text-neutral-700 dark:text-neutral-300">
|
123
|
+
Posts {posts.length}
|
124
|
+
</span>
|
125
|
+
</h1>
|
126
|
+
|
127
|
+
{user && (
|
128
|
+
<form
|
129
|
+
action={async (formData: FormData) => {
|
130
|
+
"use server"
|
131
|
+
|
132
|
+
if (!user) throw new Error("Unauthorized")
|
133
|
+
|
134
|
+
const name =
|
135
|
+
formData.get("name")?.toString() ||
|
136
|
+
`New Post ${posts.length + 1}`
|
137
|
+
|
138
|
+
await db.post.create({
|
139
|
+
data: {
|
140
|
+
id: crypto.randomUUID(),
|
141
|
+
name,
|
142
|
+
createdBy: {
|
143
|
+
connect: {
|
144
|
+
id: user.id,
|
145
|
+
},
|
146
|
+
},
|
147
|
+
},
|
148
|
+
})
|
149
|
+
|
150
|
+
revalidatePath("/")
|
151
|
+
}}
|
152
|
+
>
|
153
|
+
<input
|
154
|
+
type="text"
|
155
|
+
name="name"
|
156
|
+
placeholder="New Post"
|
157
|
+
className="h-8 rounded-md border border-neutral-300 px-2 outline-none dark:border-neutral-700 dark:bg-neutral-800"
|
158
|
+
/>
|
159
|
+
<button
|
160
|
+
type="submit"
|
161
|
+
className="ml-2 size-8 cursor-pointer rounded-md bg-neutral-200 outline-none hover:opacity-80 focus:opacity-80 dark:bg-neutral-800"
|
162
|
+
>
|
163
|
+
+
|
164
|
+
</button>
|
165
|
+
</form>
|
166
|
+
)}
|
167
|
+
</div>
|
168
|
+
|
169
|
+
<div className="grid w-full grid-cols-1 gap-2 space-y-2 sm:grid-cols-2">
|
170
|
+
{posts.map((post) => (
|
171
|
+
<div
|
172
|
+
key={post.id}
|
173
|
+
className="flex h-10 max-w-40 items-center rounded-md bg-neutral-200 px-2 py-1 dark:bg-neutral-800"
|
174
|
+
>
|
175
|
+
<span className="truncate text-sm text-neutral-700 dark:text-neutral-300">
|
176
|
+
{post.name}
|
177
|
+
</span>
|
178
|
+
{user && (
|
179
|
+
<form
|
180
|
+
action={async () => {
|
181
|
+
"use server"
|
182
|
+
|
183
|
+
if (!user) throw new Error("Unauthorized")
|
184
|
+
|
185
|
+
await db.post.delete({
|
186
|
+
where: {
|
187
|
+
id: post.id,
|
188
|
+
createdById: user.id,
|
189
|
+
},
|
190
|
+
})
|
191
|
+
|
192
|
+
revalidatePath("/")
|
193
|
+
}}
|
194
|
+
className="ml-auto"
|
195
|
+
>
|
196
|
+
<button
|
197
|
+
type="submit"
|
198
|
+
className="ml-2 cursor-pointer rounded-md text-rose-500 outline-none hover:opacity-80 focus:opacity-80"
|
199
|
+
>
|
200
|
+
x
|
201
|
+
</button>
|
202
|
+
</form>
|
203
|
+
)}
|
204
|
+
</div>
|
205
|
+
))}
|
206
|
+
</div>
|
207
|
+
</div>
|
208
|
+
</div>
|
209
|
+
|
210
|
+
<div className="flex flex-col items-center gap-1 text-sm text-neutral-600 lg:flex-row lg:gap-2 dark:text-neutral-400">
|
211
|
+
<p className="m-0">Get started by editing </p>
|
212
|
+
<a
|
213
|
+
href={fileURL}
|
214
|
+
className="rounded-md bg-neutral-200 px-2 py-1 dark:bg-neutral-800"
|
215
|
+
>
|
216
|
+
<code>src/app/page.tsx</code>
|
217
|
+
</a>
|
218
|
+
</div>
|
219
|
+
</main>
|
220
|
+
)
|
221
|
+
}
|