mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2026-04-26 15:15:19 +00:00
fix: upgrade to nextjs 16 (#888)
* Upgrade to nextjs 16 * Update sentry config * Force dynamic for health route * Upgrade eslint config * Upgrade jest * Move types to dev dependencies * Remove pages from tailwind config * Replace img with next image
This commit is contained in:
1
www/.gitignore
vendored
1
www/.gitignore
vendored
@@ -46,3 +46,4 @@ openapi-ts-error-*.log
|
|||||||
|
|
||||||
# pnpm
|
# pnpm
|
||||||
.pnpm-store
|
.pnpm-store
|
||||||
|
/v10
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { faClose } from "@fortawesome/free-solid-svg-icons";
|
import { faClose } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import type { JSX } from "react";
|
||||||
import { MouseEventHandler } from "react";
|
import { MouseEventHandler } from "react";
|
||||||
|
|
||||||
type ModalProps = {
|
type ModalProps = {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Box, Stack, Link, Heading } from "@chakra-ui/react";
|
import { Box, Stack, Link, Heading } from "@chakra-ui/react";
|
||||||
import NextLink from "next/link";
|
import NextLink from "next/link";
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Container, Flex, Link } from "@chakra-ui/react";
|
import { Container, Flex } from "@chakra-ui/react";
|
||||||
import { featureEnabled } from "../lib/features";
|
import { featureEnabled } from "../lib/features";
|
||||||
import NextLink from "next/link";
|
import NextLink from "next/link";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
@@ -30,7 +30,7 @@ export default async function AppLayout({
|
|||||||
mt="1"
|
mt="1"
|
||||||
>
|
>
|
||||||
{/* Logo on the left */}
|
{/* Logo on the left */}
|
||||||
<Link as={NextLink} href="/" className="flex">
|
<NextLink href="/" className="flex">
|
||||||
<Image
|
<Image
|
||||||
src="/reach.svg"
|
src="/reach.svg"
|
||||||
width={32}
|
width={32}
|
||||||
@@ -46,22 +46,18 @@ export default async function AppLayout({
|
|||||||
Capture the signal, not the noise
|
Capture the signal, not the noise
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</NextLink>
|
||||||
<div>
|
<div>
|
||||||
{/* Text link on the right */}
|
{/* Text link on the right */}
|
||||||
<Link
|
<NextLink href={RECORD_A_MEETING_URL} className="font-light px-2">
|
||||||
as={NextLink}
|
|
||||||
href={RECORD_A_MEETING_URL}
|
|
||||||
className="font-light px-2"
|
|
||||||
>
|
|
||||||
Create
|
Create
|
||||||
</Link>
|
</NextLink>
|
||||||
{featureEnabled("browse") ? (
|
{featureEnabled("browse") ? (
|
||||||
<>
|
<>
|
||||||
·
|
·
|
||||||
<Link href="/browse" as={NextLink} className="font-light px-2">
|
<NextLink href="/browse" className="font-light px-2">
|
||||||
Browse
|
Browse
|
||||||
</Link>
|
</NextLink>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
@@ -69,9 +65,9 @@ export default async function AppLayout({
|
|||||||
{featureEnabled("rooms") ? (
|
{featureEnabled("rooms") ? (
|
||||||
<>
|
<>
|
||||||
·
|
·
|
||||||
<Link href="/rooms" as={NextLink} className="font-light px-2">
|
<NextLink href="/rooms" className="font-light px-2">
|
||||||
Rooms
|
Rooms
|
||||||
</Link>
|
</NextLink>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
@@ -79,13 +75,9 @@ export default async function AppLayout({
|
|||||||
{featureEnabled("requireLogin") ? (
|
{featureEnabled("requireLogin") ? (
|
||||||
<>
|
<>
|
||||||
·
|
·
|
||||||
<Link
|
<NextLink href="/settings/api-keys" className="font-light px-2">
|
||||||
href="/settings/api-keys"
|
|
||||||
as={NextLink}
|
|
||||||
className="font-light px-2"
|
|
||||||
>
|
|
||||||
Settings
|
Settings
|
||||||
</Link>
|
</NextLink>
|
||||||
·
|
·
|
||||||
<UserInfo />
|
<UserInfo />
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ function WherebyConsentDialogButton({
|
|||||||
meetingId: MeetingId;
|
meetingId: MeetingId;
|
||||||
recordingType: Meeting["recording_type"];
|
recordingType: Meeting["recording_type"];
|
||||||
skipConsent: boolean;
|
skipConsent: boolean;
|
||||||
wherebyRef: React.RefObject<HTMLElement>;
|
wherebyRef: React.RefObject<HTMLElement | null>;
|
||||||
}) {
|
}) {
|
||||||
const previousFocusRef = useRef<HTMLElement | null>(null);
|
const previousFocusRef = useRef<HTMLElement | null>(null);
|
||||||
|
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ export type RoomDetails = {
|
|||||||
|
|
||||||
// stages: we focus on the consent, then whereby steals focus, then we focus on the consent again, then return focus to whoever stole it initially
|
// stages: we focus on the consent, then whereby steals focus, then we focus on the consent again, then return focus to whoever stole it initially
|
||||||
const useConsentWherebyFocusManagement = (
|
const useConsentWherebyFocusManagement = (
|
||||||
acceptButtonRef: RefObject<HTMLButtonElement>,
|
acceptButtonRef: RefObject<HTMLButtonElement | null>,
|
||||||
wherebyRef: RefObject<HTMLElement>,
|
wherebyRef: RefObject<HTMLElement | null>,
|
||||||
) => {
|
) => {
|
||||||
const currentFocusRef = useRef<HTMLElement | null>(null);
|
const currentFocusRef = useRef<HTMLElement | null>(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -87,7 +87,7 @@ const useConsentWherebyFocusManagement = (
|
|||||||
|
|
||||||
const useConsentDialog = (
|
const useConsentDialog = (
|
||||||
meetingId: MeetingId,
|
meetingId: MeetingId,
|
||||||
wherebyRef: RefObject<HTMLElement> /*accessibility*/,
|
wherebyRef: RefObject<HTMLElement | null> /*accessibility*/,
|
||||||
) => {
|
) => {
|
||||||
const { state: consentState, touch, hasAnswered } = useRecordingConsent();
|
const { state: consentState, touch, hasAnswered } = useRecordingConsent();
|
||||||
// toast would open duplicates, even with using "id=" prop
|
// toast would open duplicates, even with using "id=" prop
|
||||||
@@ -220,7 +220,7 @@ function ConsentDialogButton({
|
|||||||
wherebyRef,
|
wherebyRef,
|
||||||
}: {
|
}: {
|
||||||
meetingId: MeetingId;
|
meetingId: MeetingId;
|
||||||
wherebyRef: React.RefObject<HTMLElement>;
|
wherebyRef: React.RefObject<HTMLElement | null>;
|
||||||
}) {
|
}) {
|
||||||
const { showConsentModal, consentState, hasAnswered, consentLoading } =
|
const { showConsentModal, consentState, hasAnswered, consentLoading } =
|
||||||
useConsentDialog(meetingId, wherebyRef);
|
useConsentDialog(meetingId, wherebyRef);
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
import NextAuth from "next-auth";
|
import NextAuth from "next-auth";
|
||||||
import { authOptions } from "../../../lib/authBackend";
|
import { authOptions } from "../../../lib/authBackend";
|
||||||
|
|
||||||
const handler = NextAuth(authOptions());
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
export { handler as GET, handler as POST };
|
// authOptions() is deferred to request time to avoid calling getNextEnvVar
|
||||||
|
// during Turbopack's build-phase module evaluation (Next.js 16+)
|
||||||
|
export function GET(req: Request, ctx: any) {
|
||||||
|
return NextAuth(authOptions())(req as any, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function POST(req: Request, ctx: any) {
|
||||||
|
return NextAuth(authOptions())(req as any, ctx);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
export async function GET() {
|
export async function GET() {
|
||||||
const health = {
|
const health = {
|
||||||
status: "healthy",
|
status: "healthy",
|
||||||
|
|||||||
@@ -24,10 +24,9 @@ export const viewport: Viewport = {
|
|||||||
maximumScale: 1,
|
maximumScale: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function generateMetadata(): Metadata {
|
||||||
const SITE_URL = getNextEnvVar("SITE_URL");
|
const SITE_URL = getNextEnvVar("SITE_URL");
|
||||||
const env = getClientEnv();
|
return {
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
metadataBase: new URL(SITE_URL),
|
metadataBase: new URL(SITE_URL),
|
||||||
title: {
|
title: {
|
||||||
template: "%s – Reflector",
|
template: "%s – Reflector",
|
||||||
@@ -38,7 +37,9 @@ export const metadata: Metadata = {
|
|||||||
applicationName: "Reflector",
|
applicationName: "Reflector",
|
||||||
referrer: "origin-when-cross-origin",
|
referrer: "origin-when-cross-origin",
|
||||||
keywords: ["Reflector", "Monadical", "AI", "Meetings", "Transcription"],
|
keywords: ["Reflector", "Monadical", "AI", "Meetings", "Transcription"],
|
||||||
authors: [{ name: "Monadical Team", url: "https://monadical.com/team.html" }],
|
authors: [
|
||||||
|
{ name: "Monadical Team", url: "https://monadical.com/team.html" },
|
||||||
|
],
|
||||||
formatDetection: {
|
formatDetection: {
|
||||||
email: false,
|
email: false,
|
||||||
address: false,
|
address: false,
|
||||||
@@ -65,14 +66,21 @@ export const metadata: Metadata = {
|
|||||||
shortcut: "/r-icon.png",
|
shortcut: "/r-icon.png",
|
||||||
apple: "/r-icon.png",
|
apple: "/r-icon.png",
|
||||||
},
|
},
|
||||||
robots: { index: false, follow: false, noarchive: true, noimageindex: true },
|
robots: {
|
||||||
|
index: false,
|
||||||
|
follow: false,
|
||||||
|
noarchive: true,
|
||||||
|
noimageindex: true,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export default async function RootLayout({
|
export default async function RootLayout({
|
||||||
children,
|
children,
|
||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
|
const env = getClientEnv();
|
||||||
return (
|
return (
|
||||||
<html lang="en" className={poppins.className} suppressHydrationWarning>
|
<html lang="en" className={poppins.className} suppressHydrationWarning>
|
||||||
<body
|
<body
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ export const getClientEnvServer = (): ClientEnvCommon => {
|
|||||||
|
|
||||||
if (isBuildPhase) {
|
if (isBuildPhase) {
|
||||||
return {
|
return {
|
||||||
API_URL: getNextEnvVar("API_URL"),
|
API_URL: parseNonEmptyString(process.env.API_URL ?? ""),
|
||||||
WEBSOCKET_URL: parseMaybeNonEmptyString(process.env.WEBSOCKET_URL ?? ""),
|
WEBSOCKET_URL: parseMaybeNonEmptyString(process.env.WEBSOCKET_URL ?? ""),
|
||||||
AUTH_PROVIDER: parseAuthProvider(),
|
AUTH_PROVIDER: parseAuthProvider(),
|
||||||
SENTRY_DSN: parseMaybeNonEmptyString(
|
SENTRY_DSN: parseMaybeNonEmptyString(
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import type { JSX } from "react";
|
||||||
|
|
||||||
type SimpleProps = {
|
type SimpleProps = {
|
||||||
children: JSX.Element | string | (JSX.Element | string)[];
|
children: JSX.Element | string | (JSX.Element | string)[];
|
||||||
className?: string;
|
className?: string;
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ export default function WebinarPage(details: WebinarDetails) {
|
|||||||
<div className="max-w-4xl mx-auto px-2 py-8 bg-gray-50">
|
<div className="max-w-4xl mx-auto px-2 py-8 bg-gray-50">
|
||||||
<div className="bg-white rounded-3xl px-4 md:px-36 py-4 shadow-md mx-auto">
|
<div className="bg-white rounded-3xl px-4 md:px-36 py-4 shadow-md mx-auto">
|
||||||
<Link href="https://www.monadical.com" target="_blank">
|
<Link href="https://www.monadical.com" target="_blank">
|
||||||
<img
|
<Image
|
||||||
src="/monadical-black-white 1.svg"
|
src="/monadical-black-white 1.svg"
|
||||||
alt="Monadical Logo"
|
alt="Monadical Logo"
|
||||||
className="mx-auto mb-8"
|
className="mx-auto mb-8"
|
||||||
@@ -355,7 +355,7 @@ export default function WebinarPage(details: WebinarDetails) {
|
|||||||
<div className="max-w-4xl mx-auto px-2 py-8 bg-gray-50">
|
<div className="max-w-4xl mx-auto px-2 py-8 bg-gray-50">
|
||||||
<div className="bg-white rounded-3xl px-4 md:px-36 py-4 shadow-md mx-auto">
|
<div className="bg-white rounded-3xl px-4 md:px-36 py-4 shadow-md mx-auto">
|
||||||
<Link href="https://www.monadical.com" target="_blank">
|
<Link href="https://www.monadical.com" target="_blank">
|
||||||
<img
|
<Image
|
||||||
src="/monadical-black-white 1.svg"
|
src="/monadical-black-white 1.svg"
|
||||||
alt="Monadical Logo"
|
alt="Monadical Logo"
|
||||||
className="mx-auto mb-8"
|
className="mx-auto mb-8"
|
||||||
|
|||||||
@@ -4,47 +4,20 @@ const nextConfig = {
|
|||||||
env: {
|
env: {
|
||||||
IS_CI: process.env.IS_CI,
|
IS_CI: process.env.IS_CI,
|
||||||
},
|
},
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = nextConfig;
|
|
||||||
|
|
||||||
// Injected content via Sentry wizard below
|
|
||||||
|
|
||||||
const { withSentryConfig } = require("@sentry/nextjs");
|
|
||||||
|
|
||||||
module.exports = withSentryConfig(
|
|
||||||
module.exports,
|
|
||||||
{
|
|
||||||
// For all available options, see:
|
|
||||||
// https://github.com/getsentry/sentry-webpack-plugin#options
|
|
||||||
|
|
||||||
// Suppresses source map uploading logs during build
|
|
||||||
silent: true,
|
|
||||||
|
|
||||||
org: "monadical",
|
|
||||||
project: "reflector-www",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// For all available options, see:
|
|
||||||
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
|
|
||||||
|
|
||||||
// Upload a larger set of source maps for prettier stack traces (increases build time)
|
|
||||||
widenClientFileUpload: true,
|
|
||||||
|
|
||||||
// Transpiles SDK to be compatible with IE11 (increases bundle size)
|
|
||||||
transpileClientSDK: true,
|
|
||||||
|
|
||||||
// Routes browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers (increases server load)
|
|
||||||
tunnelRoute: "/monitoring",
|
|
||||||
|
|
||||||
// Hides source maps from generated client bundles
|
|
||||||
hideSourceMaps: true,
|
|
||||||
|
|
||||||
// Automatically tree-shake Sentry logger statements to reduce bundle size
|
|
||||||
disableLogger: true,
|
|
||||||
|
|
||||||
experimental: {
|
experimental: {
|
||||||
optimizePackageImports: ["@chakra-ui/react"],
|
optimizePackageImports: ["@chakra-ui/react"],
|
||||||
},
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const { withSentryConfig } = require("@sentry/nextjs");
|
||||||
|
|
||||||
|
module.exports = withSentryConfig(nextConfig, {
|
||||||
|
silent: true,
|
||||||
|
org: "monadical",
|
||||||
|
project: "reflector-www",
|
||||||
|
widenClientFileUpload: true,
|
||||||
|
tunnelRoute: "/monitoring",
|
||||||
|
bundleSizeOptimizations: {
|
||||||
|
excludeDebugStatements: true,
|
||||||
},
|
},
|
||||||
);
|
});
|
||||||
|
|||||||
@@ -21,17 +21,16 @@
|
|||||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
"@sentry/nextjs": "^10.40.0",
|
"@sentry/nextjs": "^10.40.0",
|
||||||
"@tanstack/react-query": "^5.85.9",
|
"@tanstack/react-query": "^5.85.9",
|
||||||
"@types/ioredis": "^5.0.0",
|
|
||||||
"@whereby.com/browser-sdk": "^3.3.4",
|
"@whereby.com/browser-sdk": "^3.3.4",
|
||||||
"autoprefixer": "10.4.20",
|
"autoprefixer": "10.4.20",
|
||||||
"axios": "^1.13.5",
|
"axios": "^1.13.5",
|
||||||
"eslint": "^9.33.0",
|
"eslint": "^9.33.0",
|
||||||
"eslint-config-next": "^15.5.3",
|
"eslint-config-next": "^16.1.6",
|
||||||
"fontawesome": "^5.6.3",
|
"fontawesome": "^5.6.3",
|
||||||
"ioredis": "^5.7.0",
|
"ioredis": "^5.7.0",
|
||||||
"jest-worker": "^29.6.2",
|
"jest-worker": "^29.6.2",
|
||||||
"lucide-react": "^0.525.0",
|
"lucide-react": "^0.525.0",
|
||||||
"next": "^15.5.10",
|
"next": "^16.1.6",
|
||||||
"next-auth": "^4.24.12",
|
"next-auth": "^4.24.12",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"nuqs": "^2.4.3",
|
"nuqs": "^2.4.3",
|
||||||
@@ -39,8 +38,8 @@
|
|||||||
"openapi-react-query": "^0.5.0",
|
"openapi-react-query": "^0.5.0",
|
||||||
"postcss": "8.4.31",
|
"postcss": "8.4.31",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"react": "^18.2.0",
|
"react": "^19.2.4",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^19.2.4",
|
||||||
"react-dropdown": "^1.11.0",
|
"react-dropdown": "^1.11.0",
|
||||||
"react-icons": "^5.0.1",
|
"react-icons": "^5.0.1",
|
||||||
"react-markdown": "^9.0.0",
|
"react-markdown": "^9.0.0",
|
||||||
@@ -61,12 +60,14 @@
|
|||||||
"author": "Andreas <andreas@monadical.com>",
|
"author": "Andreas <andreas@monadical.com>",
|
||||||
"license": "All Rights Reserved",
|
"license": "All Rights Reserved",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/ioredis": "^5.0.0",
|
||||||
"@types/jest": "^30.0.0",
|
"@types/jest": "^30.0.0",
|
||||||
"@types/react": "18.2.20",
|
"@types/react": "19.2.14",
|
||||||
"jest": "^30.1.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
|
"jest": "^30.2.0",
|
||||||
"openapi-typescript": "^7.9.1",
|
"openapi-typescript": "^7.9.1",
|
||||||
"prettier": "^3.0.0",
|
"prettier": "^3.0.0",
|
||||||
"ts-jest": "^29.4.1"
|
"ts-jest": "^29.4.6"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.14.0+sha512.ad27a79641b49c3e481a16a805baa71817a04bbe06a38d17e60e2eaee83f6a146c6a688125f5792e48dd5ba30e7da52a5cda4c3992b9ccf333f9ce223af84748"
|
"packageManager": "pnpm@10.14.0+sha512.ad27a79641b49c3e481a16a805baa71817a04bbe06a38d17e60e2eaee83f6a146c6a688125f5792e48dd5ba30e7da52a5cda4c3992b9ccf333f9ce223af84748"
|
||||||
}
|
}
|
||||||
|
|||||||
1754
www/pnpm-lock.yaml
generated
1754
www/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,6 @@ module.exports = {
|
|||||||
preflight: false,
|
preflight: false,
|
||||||
},
|
},
|
||||||
content: [
|
content: [
|
||||||
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
|
||||||
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "preserve",
|
"jsx": "react-jsx",
|
||||||
"plugins": [
|
"plugins": [
|
||||||
{
|
{
|
||||||
"name": "next"
|
"name": "next"
|
||||||
@@ -22,6 +22,12 @@
|
|||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
"downlevelIteration": true
|
"downlevelIteration": true
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", ".next/types/**/*.ts", "**/*.ts", "**/*.tsx"],
|
"include": [
|
||||||
|
"next-env.d.ts",
|
||||||
|
".next/types/**/*.ts",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
".next/dev/types/**/*.ts"
|
||||||
|
],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user