first commit
Some checks failed
Test examples / Test Examples (20) (push) Has been cancelled
Test examples / Test Examples (22) (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Trigger Release / start (push) Has been cancelled
Stale issue handler / stale (push) Has been cancelled
Update Font Data / create-pull-request (push) Has been cancelled
build-and-deploy / deploy-target (push) Has been cancelled
build-and-deploy / build (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / build-wasm (nodejs) (push) Has been cancelled
build-and-deploy / build-wasm (web) (push) Has been cancelled
build-and-deploy / Deploy preview tarball (push) Has been cancelled
build-and-deploy / Potentially publish release (push) Has been cancelled
build-and-deploy / publish-turbopack-npm-packages (push) Has been cancelled
build-and-deploy / Deploy examples (push) Has been cancelled
build-and-deploy / thank you, build (push) Has been cancelled
build-and-deploy / Upload Turbopack Bytesize metrics to Datadog (push) Has been cancelled
Rspack Next.js development integration tests / Rspack integration tests (push) Has been cancelled
Rspack Next.js production integration tests / Rspack integration tests (push) Has been cancelled
Turbopack Next.js development integration tests / Next.js integration tests (push) Has been cancelled
Turbopack Next.js production integration tests / Next.js integration tests (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack development test manifest (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack production test manifest (push) Has been cancelled
Upload bundler test manifests to areweturboyet.com / Upload test results (push) Has been cancelled
Update React / create-pull-request (push) Has been cancelled
test-e2e-project-reset-cron / reset-test-project (push) Has been cancelled
Notify about the top 15 issues/PRs/feature requests (most reacted) in the last 90 days / run (push) Has been cancelled

This commit is contained in:
Arian Tron
2026-03-10 19:37:31 +03:30
commit 61f56f997c
27684 changed files with 2784175 additions and 0 deletions

View File

@@ -0,0 +1 @@
dbschema/edgeql-js

40
examples/with-edgedb/.gitignore vendored Normal file
View File

@@ -0,0 +1,40 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

View File

@@ -0,0 +1,152 @@
# Full-stack EdgeDB + Next.js application
A simple blog application built with Next.js, TypeScript, [React](https://reactjs.org/), and [EdgeDB](https://www.edgedb.com/docs) on the backend.
## Deploy your own
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-edgedb&project-name=with-edgedb&repository-name=with-edgedb&env=EDGEDB_DSN)
## How to use
### Download the example project
Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init), [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/), or [pnpm](https://pnpm.io) to bootstrap the example:
```bash
npx create-next-app --example with-edgedb with-edgedb-app
```
```bash
yarn create next-app --example with-edgedb with-edgedb-app
```
```bash
pnpm create next-app --example with-edgedb with-edgedb-app
```
Then `cd` into the created directory.
```bash
$ cd with-edgedb-app
```
### Install the CLI
First install the EdgeDB CLI if you haven't already.
```bash
# macOS/Linux
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.edgedb.com | sh
# Windows (Powershell)
$ iwr https://ps1.edgedb.com -useb | iex
```
### Initialize the EdgeDB project
Initialize the project with the following CLI command:
```bash
$ edgedb project init
```
After you follow the prompts, this command will spin up a local EdgeDB instance and apply all the migrations inside `dbschema/migrations`. Now that the project is initialized, all EdgeDB clients initialized inside the project directory will connect to this instance automatically—no need for environment variables or hard-coded configuration. ([Read more about projects here.](https://www.edgedb.com/docs/guides/projects))
### Install dependencies
Install npm dependencies:
```bash
$ npm install
# or
$ yarn
```
### Generate the query builder
This project uses the EdgeQL query builder for TypeScript. This tool can express any EdgeQL query in a code-first way and infers a static return type. Generate it with the following command:
```bash
$ npx edgeql-js
```
The query builder consists of several files that are generated into the `dbschema/edgeql-js` directory. Import it like so:
```ts
import e from "./dbschema/edgeql-js";
```
### Seed the database
```bash
$ npx ts-node seed.ts
```
### Start the app
```bash
$ yarn dev
```
The application should now be running on http://localhost:3000.
## Notes
#### packages structure
- `/`: See all published posts
- `/drafts`: See all drafts
- `/create`: Form to create new draft
- `/blog/:id`: See either an edit page or a published post, depending on the publish status of the post.
#### API structure
- `POST /api/post`: Create a new post
- Body: `{title: string; content: string; authorName: string}`
- `PATCH /api/post/:id`: Update a post by `id`
- Body: `{title?: string; content?: string;}`
- `PUT /api/publish/:id`: Publish a post by `id`
- `DELETE /api/post/:id`: Delete a post by `id`
## Evolving the app
Evolving the application typically requires three steps:
1. Update the schema in `dbschema/default.esdl`
2. Generate a new migration with `edgedb migration create`
3. Apply the migration with `edgedb migrate`
4. Regenerate the query builder with `npx edgeql-js`
5. Update the application code, as needed.
## Deployment
To deploy this application, deploy EdgeDB to your preferred cloud provider:
- [AWS](https://www.edgedb.com/docs/guides/deployment/aws_aurora_ecs)
- [Google Cloud](https://www.edgedb.com/docs/guides/deployment/gcp)
- [Azure](https://www.edgedb.com/docs/guides/deployment/azure_flexibleserver)
- [DigitalOcean](https://www.edgedb.com/docs/guides/deployment/digitalocean)
- [Fly.io](https://www.edgedb.com/docs/guides/deployment/fly_io)
- [Docker](https://www.edgedb.com/docs/guides/deployment/docker) (cloud-agnostic)
Then:
1. Find your instance's DSN (AKA connection string). The exact instructions for this depend on which cloud you are deploying to.
2. Use this DSN to migrate your remote instance to the latest schema. Run this command from inside your project directory.
```
edgedb migrate --dsn <your-instance-dsn> --tls-security insecure
```
You have to disable TLS checks with `--tls-security insecure`. All EdgeDB instances use TLS by default, but configuring it is out of scope of this project.
3. Deploy this app to Vercel with the button above. You'll be prompted to provide a value for `EDGEDB_DSN`, the value from the previous step.
4. Open the application at the deployment URL supplied by Vercel.
## Next steps
- Check out the [EdgeDB docs](https://www.edgedb.com/docs)
- Join the EdgeDB [Discord server](https://edgedb.com/p/discord)
- Check out the code on [GitHub](https://github.com/edgedb/edgedb)

View File

@@ -0,0 +1,9 @@
import { createClient } from "edgedb";
import e from "./dbschema/edgeql-js";
// reads value of EDGEDB_DSN automatically
export const client = createClient({
// TLS configuration is beyond the scope of this example project
tlsSecurity: "insecure",
});
export { e };

View File

@@ -0,0 +1,49 @@
import React from "react";
import Link from "next/link";
const Header: React.FC = () => {
return (
<nav>
<div className="left">
<Link href="/">Blog</Link>
<Link href="/drafts">Drafts</Link>
</div>
<div className="right">
<Link href="/create">+ New draft</Link>
</div>
<style jsx>{`
nav {
display: flex;
padding: 2rem;
align-items: center;
}
.bold {
font-weight: bold;
}
a {
text-decoration: none;
color: #000;
display: inline-block;
}
a + a {
margin-left: 1rem;
}
.right {
margin-left: auto;
}
.right a {
border: 2px solid black;
padding: 0.5rem 1rem;
border-radius: 3px;
}
`}</style>
</nav>
);
};
export default Header;

View File

@@ -0,0 +1,52 @@
import React, { ReactNode } from "react";
import Header from "./Header";
type Props = {
children: ReactNode;
};
const Layout: React.FC<Props> = (props) => (
<div style={{ paddingBottom: "30px" }}>
<Header />
<div className="layout">{props.children}</div>
<style jsx global>{`
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
padding: 0;
font-size: 16px;
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol";
background: rgba(0, 0, 0, 0);
}
input,
textarea,
button {
font-size: 16px;
}
button {
cursor: pointer;
}
`}</style>
<style jsx>{`
.layout {
padding: 0 2rem;
}
`}</style>
</div>
);
export default Layout;

View File

@@ -0,0 +1,40 @@
import React from "react";
import { Streamdown } from "streamdown";
import Link from "next/link";
import { PostProps } from "../pages/blog/[id]";
const Post: React.FC<{ post: PostProps }> = ({ post }) => {
return (
<Link href={`/blog/${post.id}`}>
<div>
<h2>{post.title}</h2>
<small>By {post.authorName}</small>
<br />
<br />
<Streamdown mode="static" className="streamdown">
{post.content || ""}
</Streamdown>
<style jsx>{`
div {
color: inherit;
padding: 2rem;
cursor: pointer;
}
h2 {
margin: 0px;
padding-bottom: 4px;
}
small {
color: #888;
}
.streamdown,
.streamdown > p {
margin: 0px;
}
`}</style>
</div>
</Link>
);
};
export default Post;

View File

@@ -0,0 +1,11 @@
module default {
type Post {
required property title -> str;
required property content -> str { default := '' };
required property authorName -> str { default := 'Unknown author' };
property published -> datetime;
property publishedISO := <str>.published;
}
}

View File

@@ -0,0 +1,15 @@
CREATE MIGRATION m1gcnribdubi476w7daqzhuxvbutfpiqyhhbm2nyfv3xhzc6z757ia
ONTO initial
{
CREATE TYPE default::Post {
CREATE REQUIRED PROPERTY authorName -> std::str {
SET default := 'Unknown author';
};
CREATE REQUIRED PROPERTY content -> std::str {
SET default := '';
};
CREATE PROPERTY published -> std::datetime;
CREATE PROPERTY publishedISO := (<std::str>.published);
CREATE REQUIRED PROPERTY title -> std::str;
};
};

View File

@@ -0,0 +1,2 @@
[edgedb]
server-version = "2"

View File

@@ -0,0 +1,28 @@
{
"private": true,
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start",
"seed": "ts-node dbschema/seed.ts",
"prebuild": "npx edgeql-js"
},
"dependencies": {
"@types/react": "^18.0.5",
"@types/react-dom": "^18.0.1",
"edgedb": "latest",
"next": "latest",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"streamdown": "^1.6.5"
},
"devDependencies": {
"autoprefixer": "^10.4.20",
"@types/node": "^16.11.26",
"postcss": "^8.4.49",
"prettier": "^2.6.2",
"tailwindcss": "^3.4.16",
"ts-node": "^10.7.0",
"typescript": "^4.6.3"
}
}

View File

@@ -0,0 +1,44 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { client, e } from "../../../client";
// PATCH /api/post/:id
async function updatePost(
postId: string,
data: { title?: string; content?: string },
) {
return await e
.update(e.Post, (post) => ({
filter: e.op(post.id, "=", e.uuid(postId)),
set: {
title: data.title,
content: data.content,
},
}))
.run(client);
}
// DELETE /api/post/:id
async function deletePost(postId: string) {
return await e
.delete(e.Post, (post) => ({
filter: e.op(post.id, "=", e.uuid(postId)),
}))
.run(client);
}
export default async function handle(
req: NextApiRequest,
res: NextApiResponse,
) {
const postId = req.query.id as string;
if (req.method === "DELETE") {
res.json(await deletePost(postId));
} else if (req.method === "PATCH") {
res.json(await updatePost(postId, req.body));
} else {
throw new Error(
`The HTTP ${req.method} method is not supported at this route.`,
);
}
}

View File

@@ -0,0 +1,20 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { client, e } from "../../../client";
// POST /api/post
// body {title: string; content: string; authorName: string}
export default async function handle(
req: NextApiRequest,
res: NextApiResponse,
) {
const { title, content, authorName } = req.body;
const result = await e
.insert(e.Post, {
title,
content,
authorName,
})
.run(client);
res.json(result);
}

View File

@@ -0,0 +1,19 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { client, e } from "../../../client";
// PUT /api/publish/:id
export default async function handle(
req: NextApiRequest,
res: NextApiResponse,
) {
const postId = req.query.id as string;
const post = await e
.update(e.Post, (post) => ({
filter: e.op(post.id, "=", e.uuid(postId)),
set: {
published: e.std.datetime_of_statement(),
},
}))
.run(client);
res.json(post);
}

View File

@@ -0,0 +1,171 @@
import React, { useState } from "react";
import { GetServerSidePropsContext, InferGetServerSidePropsType } from "next";
import { Streamdown } from "streamdown";
import Layout from "../../components/Layout";
import Router from "next/router";
import { client, e } from "../../client";
async function update(
id: string,
data: { title?: string; content?: string },
): Promise<void> {
await fetch(`/api/post/${id}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
alert("Draft saved!");
}
async function publish(id: string): Promise<void> {
await fetch(`/api/publish/${id}`, {
method: "PUT",
});
await Router.push(`/blog/${id}`);
}
async function destroy(id: string): Promise<void> {
await fetch(`/api/post/${id}`, {
method: "DELETE",
});
await Router.push("/");
}
const Post: React.FC<PostProps> = (props) => {
const [patch, setPatch] = useState<{
title?: string;
content?: string;
}>({
title: props.title,
content: props.content || undefined,
});
if (props.publishedISO) {
return (
<Layout>
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "stretch",
margin: "auto",
maxWidth: "600px",
}}
>
<h1 style={{ paddingTop: "100px", margin: 0, paddingBottom: "8px" }}>
{props.title}
</h1>
<p style={{ fontSize: "14pt", margin: 0, color: "#888" }}>
By {props.authorName}
</p>
<br />
<br />
<Streamdown mode="static">{props.content || ""}</Streamdown>
</div>
</Layout>
);
}
return (
<Layout>
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "stretch",
}}
>
<input
value={patch.title}
onChange={(e) => {
setPatch({ ...patch, title: e.target.value });
}}
/>
<textarea
rows={25}
value={patch.content || ""}
onChange={(e) => {
setPatch({ ...patch, content: e.target.value });
}}
/>
<div style={{ display: "flex", flexDirection: "row" }}>
<button
style={{ backgroundColor: "#0E61FE", color: "white" }}
onClick={() => update(props.id, patch)}
>
{props.publishedISO ? "Update" : "Save draft"}
</button>
{!props.publishedISO && (
<button
style={{ backgroundColor: "#0E61FE", color: "white" }}
onClick={() => publish(props.id)}
>
Publish
</button>
)}
<button
style={{ border: "2px solid red", color: "red" }}
onClick={() => destroy(props.id)}
>
Delete
</button>
</div>
</div>
<style jsx>{`
.page {
padding: 2rem;
}
h2 {
margin: 0px;
}
input {
font-size: 20pt;
}
textarea,
input {
margin: 0 0 0.75rem 0;
padding: 0.5rem;
border: 0.125rem solid rgba(0, 0, 0, 0.2);
border-radius: 0.25rem;
}
.actions {
margin-top: 2rem;
}
button {
border: 2px solid transparent;
border-radius: 4px;
padding: 0.5rem 1.25rem;
background-color: unset;
}
button + button {
margin-left: 0.5rem;
}
`}</style>
</Layout>
);
};
export const getServerSideProps = async (
context?: GetServerSidePropsContext,
) => {
const post = await e
.select(e.Post, (post) => ({
id: true,
title: true,
content: true,
publishedISO: true,
authorName: true,
filter: e.op(post.id, "=", e.uuid(context!.params!.id as string)),
}))
.run(client);
return { props: post! };
};
export type PostProps = InferGetServerSidePropsType<typeof getServerSideProps>;
export default Post;

View File

@@ -0,0 +1,97 @@
import React, { useState } from "react";
import Layout from "../components/Layout";
import Router from "next/router";
import Link from "next/link";
const Draft: React.FC = () => {
const [title, setTitle] = useState("");
const [content, setContent] = useState("");
const [authorName, setAuthorName] = useState("");
const submitData = async (e: React.SyntheticEvent) => {
e.preventDefault();
try {
const body = { title, content, authorName };
const result = await fetch(`/api/post`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
await result.json();
await Router.push("/drafts");
} catch (error) {
console.error(error);
}
};
return (
<Layout>
<div>
<form onSubmit={submitData}>
<h1>Create draft</h1>
<input
autoFocus
onChange={(e) => setTitle(e.target.value)}
placeholder="Title"
type="text"
value={title}
/>
<input
onChange={(e) => setAuthorName(e.target.value)}
placeholder="Author name"
type="text"
value={authorName}
/>
<textarea
cols={50}
onChange={(e) => setContent(e.target.value)}
placeholder="Content"
rows={8}
value={content}
/>
<input
disabled={!content || !title || !authorName}
type="submit"
value="Create"
/>
<Link href="/" className="back">
Cancel
</Link>
</form>
</div>
<style jsx>{`
.page {
background: white;
padding: 3rem;
display: flex;
justify-content: center;
align-items: center;
}
input[type="text"],
textarea {
width: 100%;
padding: 0.5rem;
margin: 0 0 0.75rem 0;
border-radius: 0.25rem;
border: 0.125rem solid rgba(0, 0, 0, 0.2);
}
input[type="submit"] {
cursor: pointer;
border: 2px solid transparent;
border-radius: 4px;
padding: 0.5rem 1.25rem;
background-color: #0e61fe;
color: white;
}
.back {
margin-left: 1rem;
}
`}</style>
</Layout>
);
};
export default Draft;

View File

@@ -0,0 +1,62 @@
import React from "react";
import { GetServerSideProps } from "next";
import Layout from "../components/Layout";
import Post from "../components/Post";
import { PostProps } from "./blog/[id]";
import { client, e } from "../client";
type Props = {
drafts: PostProps[];
};
const Drafts: React.FC<Props> = (props) => {
return (
<Layout>
<div className="page">
<h1>Drafts</h1>
<main>
{props.drafts.length
? props.drafts.map((post) => (
<div key={post.id} className="post">
<Post post={post} />
</div>
))
: "No drafts yet."}
</main>
</div>
<style jsx>{`
.post {
transition: box-shadow 0s ease-in;
border: 2px solid #eee;
border-radius: 8px;
}
.post:hover {
box-shadow: 0px 2px 8px #ccc;
border: 2px solid #727272;
}
.post + .post {
margin-top: 1rem;
}
`}</style>
</Layout>
);
};
export const getServerSideProps: GetServerSideProps = async () => {
const drafts = await e
.select(e.Post, (post) => ({
id: true,
title: true,
content: true,
authorName: true,
filter: e.op("not", e.op("exists", post.published)),
}))
.run(client);
return {
props: { drafts },
};
};
export default Drafts;

View File

@@ -0,0 +1,66 @@
import React from "react";
import "../styles/global.css";
import { GetServerSideProps } from "next";
import Layout from "../components/Layout";
import Post from "../components/Post";
import { PostProps } from "./blog/[id]";
import { client, e } from "../client";
type Props = {
feed: PostProps[];
};
const Blog: React.FC<Props> = (props) => {
return (
<Layout>
<div className="page">
<h1>Published posts</h1>
<main>
{props.feed.length ? (
props.feed.map((post) => (
<div key={post.id} className="post">
<Post post={post} />
</div>
))
) : (
<p>No blog posts yet.</p>
)}
</main>
</div>
<style jsx>{`
.post {
transition: box-shadow 0s ease-in;
border: 2px solid #eee;
border-radius: 8px;
}
.post:hover {
box-shadow: 0px 2px 8px #ccc;
border: 2px solid #727272;
}
.post + .post {
margin-top: 1rem;
}
`}</style>
</Layout>
);
};
export const getServerSideProps: GetServerSideProps = async () => {
const feed = await e
.select(e.Post, (post) => ({
id: true,
title: true,
content: true,
authorName: true,
publishedISO: true,
filter: e.op("exists", post.published),
}))
.run(client);
return {
props: { feed },
};
};
export default Blog;

View File

@@ -0,0 +1,8 @@
// If you want to use other PostCSS plugins, see the following:
// https://tailwindcss.com/docs/using-with-preprocessors
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

View File

@@ -0,0 +1,51 @@
import { client, e } from "./client";
const posts = [
{
title: "Join the EdgeDB Discord",
content: "Just follow [this link](https://edgedb.com/p/discord).",
published: true,
authorName: "Bobby",
},
{
title: "Follow EdgeDB on Twitter",
content: "We're [@edgedatabase](https://www.twitter.com/edgedatabase).",
published: true,
authorName: "Sally",
},
{
title: "Star EdgeDB on GitHub",
content:
"The repo is at [github.com/edgedb/edgedb](https://www.github.com/edgedb/edgedb).",
published: true,
authorName: "Polly",
},
{
title: "Try the EdgeDB query builder for TypeScript",
content:
"The docs are [here](https://www.edgedb.com/docs/clients/01_js/index).",
published: false,
authorName: "Polly",
},
];
async function main() {
console.log(`Start seeding...`);
for (const post of posts) {
const newPost = await e
.insert(e.Post, {
...post,
published: post.published ? e.std.datetime_current() : null,
})
.run(client);
console.log(`Created Post ${newPost.id}`);
}
console.log(`Seeding complete!`);
}
main().catch((e) => {
console.error(e);
process.exit(1);
});

View File

@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -0,0 +1,11 @@
module.exports = {
content: [
"./pages/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
"./node_modules/streamdown/dist/*.js", // For Streamdown
],
theme: {
extend: {},
},
plugins: [],
};

View File

@@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"downlevelIteration": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"incremental": true
},
"exclude": ["node_modules"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"ts-node": {
"compilerOptions": {
"module": "commonjs"
}
}
}