mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-04 13:23:28 +00:00
move releases and expression of interest into landing (#848)
* move releases and expression of interest into landing * fix eslint on landing * fs routing kinda sucks * fix waitlist link * cringe
This commit is contained in:
parent
a470844f85
commit
9fb72a1dc8
|
@ -49,7 +49,7 @@
|
||||||
"active": false,
|
"active": false,
|
||||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEZBMURCMkU5NEU3NDAyOEMKUldTTUFuUk82YklkK296dlkxUGkrTXhCT3ZMNFFVOWROcXNaS0RqWU1kMUdRV2tDdFdIS0Y3YUsK",
|
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEZBMURCMkU5NEU3NDAyOEMKUldTTUFuUk82YklkK296dlkxUGkrTXhCT3ZMNFFVOWROcXNaS0RqWU1kMUdRV2tDdFdIS0Y3YUsK",
|
||||||
"endpoints": [
|
"endpoints": [
|
||||||
"https://releases-6oxwxxryr-spacedrive.vercel.app/{{target}}/{{arch}}/{{current_version}}"
|
"https://spacedrive.com/api/releases/{{target}}/{{arch}}/{{current_version}}"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"allowlist": {
|
"allowlist": {
|
||||||
|
|
8
apps/landing/drizzle.config.ts
Normal file
8
apps/landing/drizzle.config.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import 'dotenv/config';
|
||||||
|
import { Config } from 'drizzle-kit';
|
||||||
|
import { env } from './src/env';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
schema: ['./src/server/db.ts'],
|
||||||
|
connectionString: env.DATABASE_URL
|
||||||
|
} satisfies Config;
|
1
apps/landing/next-env.d.ts
vendored
1
apps/landing/next-env.d.ts
vendored
|
@ -1,5 +1,6 @@
|
||||||
/// <reference types="next" />
|
/// <reference types="next" />
|
||||||
/// <reference types="next/image-types/global" />
|
/// <reference types="next/image-types/global" />
|
||||||
|
/// <reference types="next/navigation-types/compat/navigation" />
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
// NOTE: This file should not be edited
|
||||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
const { withContentlayer } = require('next-contentlayer');
|
import { withContentlayer } from 'next-contentlayer';
|
||||||
|
// Validate env on build
|
||||||
|
import './src/env.js';
|
||||||
|
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
|
@ -37,4 +39,4 @@ const nextConfig = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = withContentlayer(nextConfig);
|
export default withContentlayer(nextConfig);
|
|
@ -1,20 +1,27 @@
|
||||||
{
|
{
|
||||||
"name": "@sd/landing",
|
"name": "@sd/landing",
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "contentlayer build && next build",
|
"build": "contentlayer build && next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"prod": "pnpm build && pnpm start",
|
"prod": "pnpm build && pnpm start",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
"typecheck": "contentlayer build && tsc -b"
|
"typecheck": "contentlayer build && tsc -b",
|
||||||
|
"push": "drizzle-kit push:mysql"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@aws-sdk/client-ses": "^3.337.0",
|
||||||
"@icons-pack/react-simple-icons": "^7.2.0",
|
"@icons-pack/react-simple-icons": "^7.2.0",
|
||||||
|
"@planetscale/database": "^1.7.0",
|
||||||
"@sd/assets": "workspace:*",
|
"@sd/assets": "workspace:*",
|
||||||
"@sd/ui": "workspace:*",
|
"@sd/ui": "workspace:*",
|
||||||
|
"@t3-oss/env-nextjs": "^0.3.1",
|
||||||
|
"@vercel/edge-config": "^0.1.11",
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"contentlayer": "^0.3.2",
|
"contentlayer": "^0.3.2",
|
||||||
|
"drizzle-orm": "^0.26.0",
|
||||||
"markdown-to-jsx": "^7.2.0",
|
"markdown-to-jsx": "^7.2.0",
|
||||||
"next": "13.4.3",
|
"next": "13.4.3",
|
||||||
"next-contentlayer": "^0.3.2",
|
"next-contentlayer": "^0.3.2",
|
||||||
|
@ -33,7 +40,8 @@
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
"remark-math": "^5.1.1",
|
"remark-math": "^5.1.1",
|
||||||
"sharp": "^0.32.1",
|
"sharp": "^0.32.1",
|
||||||
"tsparticles": "^2.9.3"
|
"tsparticles": "^2.9.3",
|
||||||
|
"zod": "^3.21.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sd/config": "workspace:*",
|
"@sd/config": "workspace:*",
|
||||||
|
@ -43,6 +51,7 @@
|
||||||
"@types/react-burger-menu": "^2.8.3",
|
"@types/react-burger-menu": "^2.8.3",
|
||||||
"@types/react-dom": "18.2.4",
|
"@types/react-dom": "18.2.4",
|
||||||
"@types/react-helmet": "^6.1.6",
|
"@types/react-helmet": "^6.1.6",
|
||||||
|
"drizzle-kit": "db-push",
|
||||||
"postcss": "^8.4.23",
|
"postcss": "^8.4.23",
|
||||||
"tailwindcss": "^3.3.2",
|
"tailwindcss": "^3.3.2",
|
||||||
"typescript": "5.0.4"
|
"typescript": "5.0.4"
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import { get } from '@vercel/edge-config';
|
import { get } from '@vercel/edge-config';
|
||||||
import { NextResponse } from 'next/server';
|
import { NextResponse } from 'next/server';
|
||||||
|
|
||||||
export const config = {
|
export const runtime = 'edge';
|
||||||
runtime: 'edge'
|
|
||||||
};
|
|
||||||
|
|
||||||
export async function GET(
|
export async function GET(
|
||||||
_: Request,
|
_: Request,
|
112
apps/landing/src/app/api/waitlist/route.ts
Normal file
112
apps/landing/src/app/api/waitlist/route.ts
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
import type { NextRequest } from 'next/server';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { sendEmail } from '~/server/aws';
|
||||||
|
import { db, eq, waitlistTable } from '~/server/db';
|
||||||
|
import { welcomeTemplate } from './welcomeEmail';
|
||||||
|
|
||||||
|
export const runtime = 'edge';
|
||||||
|
|
||||||
|
const emailSchema = z.object({
|
||||||
|
email: z
|
||||||
|
.string({
|
||||||
|
required_error: 'Email is required',
|
||||||
|
invalid_type_error: 'Email must be a string'
|
||||||
|
})
|
||||||
|
.email({
|
||||||
|
message: 'Invalid email address'
|
||||||
|
})
|
||||||
|
.transform((value) => value.toLowerCase())
|
||||||
|
});
|
||||||
|
|
||||||
|
function randomId(len = 10) {
|
||||||
|
if (len % 2 !== 0) throw new Error('len must be a multiple of 2');
|
||||||
|
const array = new Uint8Array(len / 2); // 1 char int to 2 chars hex
|
||||||
|
self.crypto.getRandomValues(array);
|
||||||
|
return [...array].map((c) => c.toString(16).padStart(2, '0')).join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(req: NextRequest) {
|
||||||
|
const result = emailSchema.safeParse(await req.json());
|
||||||
|
if (!result.success) {
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
message: result.error.toString()
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
status: 400
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { email } = result.data;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const emailExist = await db.select({ email: waitlistTable.email }).from(waitlistTable);
|
||||||
|
if (emailExist.length > 0) {
|
||||||
|
return new Response(undefined, {
|
||||||
|
status: 204
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsubId = randomId(26);
|
||||||
|
await db.insert(waitlistTable).values({
|
||||||
|
cuid: unsubId,
|
||||||
|
email,
|
||||||
|
created_at: new Date()
|
||||||
|
});
|
||||||
|
|
||||||
|
await sendEmail(
|
||||||
|
email,
|
||||||
|
'Welcome to Spacedrive',
|
||||||
|
welcomeTemplate(`https://spacedrive.com/?wunsub=${unsubId}`)
|
||||||
|
);
|
||||||
|
|
||||||
|
return new Response(null, {
|
||||||
|
status: 204
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
message: 'Something went wrong while trying to create invite'
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
status: 500,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DELETE(req: NextRequest) {
|
||||||
|
const url = new URL(req.url);
|
||||||
|
|
||||||
|
const id = url.searchParams.get('i');
|
||||||
|
if (!id)
|
||||||
|
return new Response(JSON.stringify(undefined), {
|
||||||
|
status: 400
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await db.delete(waitlistTable).where(eq(waitlistTable.cuid, id));
|
||||||
|
|
||||||
|
return new Response(null, {
|
||||||
|
status: 204
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
message: 'Something went wrong while trying to unsubscribe from waitlist'
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
status: 500,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
25
apps/landing/src/app/api/waitlist/welcomeEmail.ts
Normal file
25
apps/landing/src/app/api/waitlist/welcomeEmail.ts
Normal file
File diff suppressed because one or more lines are too long
|
@ -20,17 +20,12 @@ export function HomeCTA() {
|
||||||
const [waitlistSubmitted, setWaitlistSubmitted] = useState(false);
|
const [waitlistSubmitted, setWaitlistSubmitted] = useState(false);
|
||||||
const [fire, setFire] = useState<boolean | number>(false);
|
const [fire, setFire] = useState<boolean | number>(false);
|
||||||
|
|
||||||
const url =
|
|
||||||
process.env.NODE_ENV === 'production'
|
|
||||||
? 'https://waitlist-api.spacedrive.com'
|
|
||||||
: 'http://localhost:3000';
|
|
||||||
|
|
||||||
async function handleWaitlistSubmit<SubmitHandler>({ email }: WaitlistInputs) {
|
async function handleWaitlistSubmit<SubmitHandler>({ email }: WaitlistInputs) {
|
||||||
if (!email.trim().length) return;
|
if (!email.trim().length) return;
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
const req = await fetch(`${url}/api/waitlist`, {
|
const req = await fetch(`/api/waitlist`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
|
|
31
apps/landing/src/env.js
Normal file
31
apps/landing/src/env.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// @ts-check
|
||||||
|
//
|
||||||
|
// Has to be `.mjs` so it can be imported in `next.config.mjs`.
|
||||||
|
// Next.js are so cringe for not having support for Typescript config files.
|
||||||
|
//
|
||||||
|
// Using `.mjs` with Drizzle Kit is seemingly impossible without `.ts` so we resort to `.js`.
|
||||||
|
// Why does JS make this shit so hard, I just wanna import the file.
|
||||||
|
//
|
||||||
|
import { createEnv } from '@t3-oss/env-nextjs';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
export const env = createEnv({
|
||||||
|
server: {
|
||||||
|
DATABASE_URL: z.string().url(),
|
||||||
|
AWS_SES_ACCESS_KEY: z.string(),
|
||||||
|
AWS_SES_SECRET_KEY: z.string(),
|
||||||
|
AWS_SES_REGION: z.string(),
|
||||||
|
MAILER_FROM: z.string().default('Spacedrive <no-reply@spacedrive.com>')
|
||||||
|
},
|
||||||
|
client: {},
|
||||||
|
runtimeEnv: {
|
||||||
|
DATABASE_URL: process.env.DATABASE_URL,
|
||||||
|
AWS_SES_ACCESS_KEY: process.env.AWS_SES_ACCESS_KEY,
|
||||||
|
AWS_SES_SECRET_KEY: process.env.AWS_SES_SECRET_KEY,
|
||||||
|
AWS_SES_REGION: process.env.AWS_SES_REGION,
|
||||||
|
MAILER_FROM: process.env.MAILER_FROM
|
||||||
|
},
|
||||||
|
// In dev or in eslint disable checking.
|
||||||
|
// Kinda sucks for in dev but you don't need the whole setup to change the docs.
|
||||||
|
skipValidation: process.env.VERCEL !== '1'
|
||||||
|
});
|
|
@ -1,13 +0,0 @@
|
||||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
|
||||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
|
||||||
|
|
||||||
type Data = {
|
|
||||||
name: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function handler(
|
|
||||||
req: NextApiRequest,
|
|
||||||
res: NextApiResponse<Data>
|
|
||||||
) {
|
|
||||||
res.status(200).json({ name: 'John Doe' })
|
|
||||||
}
|
|
|
@ -57,9 +57,8 @@ export default function HomePage() {
|
||||||
(async () => {
|
(async () => {
|
||||||
console.log('Unsubscribing from waitlist', process.env.NODE_ENV);
|
console.log('Unsubscribing from waitlist', process.env.NODE_ENV);
|
||||||
const prod = process.env.NODE_ENV === 'production';
|
const prod = process.env.NODE_ENV === 'production';
|
||||||
const url = prod ? 'https://waitlist-api.spacedrive.com' : 'http://localhost:3000';
|
|
||||||
|
|
||||||
const req = await fetch(`${url}/api/waitlist?i=${cuid}`, {
|
const req = await fetch(`/api/waitlist?i=${cuid}`, {
|
||||||
method: 'DELETE'
|
method: 'DELETE'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
33
apps/landing/src/server/aws.ts
Normal file
33
apps/landing/src/server/aws.ts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import { SESClient, SendEmailCommand } from '@aws-sdk/client-ses';
|
||||||
|
import { env } from '~/env';
|
||||||
|
|
||||||
|
export const ses = new SESClient({
|
||||||
|
region: env.AWS_SES_REGION,
|
||||||
|
credentials: {
|
||||||
|
accessKeyId: env.AWS_SES_ACCESS_KEY,
|
||||||
|
secretAccessKey: env.AWS_SES_SECRET_KEY
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export async function sendEmail(email: string, subject: string, body: string) {
|
||||||
|
await ses.send(
|
||||||
|
new SendEmailCommand({
|
||||||
|
Destination: {
|
||||||
|
ToAddresses: [email]
|
||||||
|
},
|
||||||
|
Message: {
|
||||||
|
Body: {
|
||||||
|
Html: {
|
||||||
|
Charset: 'UTF-8',
|
||||||
|
Data: body
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Subject: {
|
||||||
|
Charset: 'UTF-8',
|
||||||
|
Data: subject
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Source: env.MAILER_FROM
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
23
apps/landing/src/server/db.ts
Normal file
23
apps/landing/src/server/db.ts
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import { connect } from '@planetscale/database';
|
||||||
|
import { mysqlTable, serial, timestamp, varchar } from 'drizzle-orm/mysql-core';
|
||||||
|
import { drizzle } from 'drizzle-orm/planetscale-serverless';
|
||||||
|
import { env } from '~/env';
|
||||||
|
|
||||||
|
export { eq, and, or, type InferModel } from 'drizzle-orm';
|
||||||
|
|
||||||
|
const dbConnection = connect({
|
||||||
|
url: env.DATABASE_URL
|
||||||
|
});
|
||||||
|
|
||||||
|
export const db = drizzle(dbConnection);
|
||||||
|
|
||||||
|
export const waitlistTable = mysqlTable('waitlist', {
|
||||||
|
id: serial('id').primaryKey(),
|
||||||
|
cuid: varchar('cuid', {
|
||||||
|
length: 26
|
||||||
|
}).notNull(),
|
||||||
|
email: varchar('email', {
|
||||||
|
length: 255
|
||||||
|
}).notNull(),
|
||||||
|
created_at: timestamp('created_at').notNull()
|
||||||
|
});
|
|
@ -21,8 +21,20 @@
|
||||||
"paths": {
|
"paths": {
|
||||||
"~/*": ["./src/*"],
|
"~/*": ["./src/*"],
|
||||||
"@contentlayer/generated": ["./.contentlayer/generated"]
|
"@contentlayer/generated": ["./.contentlayer/generated"]
|
||||||
}
|
},
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
"include": [
|
||||||
|
"next-env.d.ts",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
"src/env.js",
|
||||||
|
"src/drizzle.config.ts",
|
||||||
|
".next/types/**/*.ts"
|
||||||
|
],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|
35
apps/releases/.gitignore
vendored
35
apps/releases/.gitignore
vendored
|
@ -1,35 +0,0 @@
|
||||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
||||||
|
|
||||||
# dependencies
|
|
||||||
/node_modules
|
|
||||||
/.pnp
|
|
||||||
.pnp.js
|
|
||||||
|
|
||||||
# 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
|
|
|
@ -1,8 +0,0 @@
|
||||||
/** @type {import('next').NextConfig} */
|
|
||||||
const nextConfig = {
|
|
||||||
experimental: {
|
|
||||||
appDir: true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = nextConfig;
|
|
|
@ -1,23 +0,0 @@
|
||||||
{
|
|
||||||
"name": "releases",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"dev": "next dev",
|
|
||||||
"build": "next build",
|
|
||||||
"start": "next start",
|
|
||||||
"lint": "next lint --strict"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": "18.15.11",
|
|
||||||
"@types/react": "18.0.35",
|
|
||||||
"@types/react-dom": "18.0.11",
|
|
||||||
"@vercel/edge-config": "^0.1.7",
|
|
||||||
"eslint-config-next": "13.3.0",
|
|
||||||
"next": "13.3.0",
|
|
||||||
"octokit": "^2.0.14",
|
|
||||||
"react": "18.2.0",
|
|
||||||
"react-dom": "^18.2.0",
|
|
||||||
"typescript": "5.0.4"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "es5",
|
|
||||||
"lib": ["dom", "dom.iterable", "esnext"],
|
|
||||||
"allowJs": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"strict": true,
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"noEmit": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"module": "esnext",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
"jsx": "preserve",
|
|
||||||
"incremental": true,
|
|
||||||
"plugins": [
|
|
||||||
{
|
|
||||||
"name": "next"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"paths": {
|
|
||||||
"~/*": ["./*"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
||||||
"exclude": ["node_modules"]
|
|
||||||
}
|
|
1762
pnpm-lock.yaml
1762
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue