OAP-18 Create basic framework to view books through OAPEN (rough is OK) (#5)

* Create items/ route

* Add basic query

* Vercel

* Fix typo

* Fix type

* Cleaner exports

* Explain expandable
pull/7/head
Justin O'Boyle 2022-10-03 21:34:11 -04:00 committed by GitHub
parent e005787bbe
commit 4a4a318c68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 463 additions and 8 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.vercel

View File

@ -1,4 +1,4 @@
import { APP_NAME_TEXT, APP_DESCRIPTION } from "../constants";
import { APP_NAME_TEXT, APP_DESCRIPTION } from "../../constants";
import Head from "next/head";
interface SEOComponents {

View File

@ -0,0 +1,66 @@
import { OAPENItemWithMetadata } from "../../lib/oapen/OAPENTypes";
export const RenderItem = ({ item }: { item: OAPENItemWithMetadata }) => {
const type = item.metadata.find(({ key }) => key == "dc.type")?.value;
if (type == "book") return <RenderBook book={transformToBook(item)} />;
return (
<>
<h1>Could not render this item with type {type}</h1>
<br />
<code>
<pre>{JSON.stringify(item, null, 4)}</pre>
</code>
</>
);
};
interface InternalBook {
title?: string;
author?: string;
// date
accessioned?: string;
issued?: string;
uri?: string;
abstract?: string;
language?: string;
classification?: string;
altTitle?: string;
publisherName?: string;
pageCount?: string;
item: OAPENItemWithMetadata;
}
const transformToBook = (item: OAPENItemWithMetadata) => {
return {
item,
title: item.metadata.find(({ key }) => key == "dc.title")?.value,
author: item.metadata.find(({ key }) => key == "dc.contributor.author")
?.value,
accessioned: item.metadata.find(({ key }) => key == "dc.date.accessioned")
?.value,
issued: item.metadata.find(({ key }) => key == "dc.date.issued")?.value,
uri: item.metadata.find(({ key }) => key == "dc.identifier.uri")?.value,
abstract: item.metadata.find(({ key }) => key == "dc.description.abstract")
?.value,
language: item.metadata.find(({ key }) => key == "dc.language")?.value,
classification: item.metadata.find(
({ key }) => key == "dc.subject.classification"
)?.value,
altTitle: item.metadata.find(({ key }) => key == "dc.title.alternative")
?.value,
publisherName: item.metadata.find(({ key }) => key == "publisher.name")
?.value,
pageCount: item.metadata.find(({ key }) => key == "oapen.pages")?.value,
};
};
export const RenderBook = ({ book }: { book: InternalBook }) => {
return (
<>
<h1>{book?.title}</h1>
<h2>
by {book?.author} ({book?.pageCount} pages)
</h2>
<p>{book?.abstract}</p>
</>
);
};

View File

@ -0,0 +1,37 @@
export type OAPENTypeID = string;
export type OAPENHandle = string;
export type OAPENType = string;
export type OAPENExpandable = string;
export type OAPENBitstreams = string;
export type OAPENApiRelativePath = string;
export type URL = string;
export interface Expandable {
// OAPEN returns a list of "expandables" -- things you can further query for additionally (like metadata). Once the expandable is added to the object, it's removed from this list.
expand?: OAPENExpandable[];
}
export interface OAPENItemRaw {
uuid: OAPENTypeID;
name?: string;
handle?: OAPENHandle;
type?: OAPENType;
archived: boolean;
withdrawn: boolean;
link?: OAPENApiRelativePath;
}
export interface RawMetadataItem {
key: string;
value: string;
qualifier?: string;
language?: string;
element?: string;
}
type HasMetadata = {
metadata: RawMetadataItem[];
};
export type OAPENItemQueried = OAPENItemRaw & Expandable;
export type OAPENItemWithMetadata = OAPENItemQueried & HasMetadata;

1
web/lib/oapen/index.ts Normal file
View File

@ -0,0 +1 @@
export * as OAPENItems from "./items";

69
web/lib/oapen/items.ts Normal file
View File

@ -0,0 +1,69 @@
import type {
OAPENItemQueried,
OAPENExpandable,
OAPENApiRelativePath,
OAPENType,
OAPENTypeID,
OAPENItemRaw,
RawMetadataItem,
OAPENItemWithMetadata,
} from "./OAPENTypes";
import { get } from "./query";
const transformRawItemQueried = (item: any) => {
return {
uuid: item.uuid as OAPENTypeID,
name: (item?.name || "") as string,
handle: item?.handle as string,
type: item?.type as OAPENType,
// comes in sometimes as string or boolean, if null return false
archived: Boolean(item?.archived),
withdrawn: Boolean(item?.withdrawn),
link: item?.link as OAPENApiRelativePath,
expand: item?.expand as OAPENExpandable[],
} as OAPENItemQueried;
};
export const getItemsRaw = async (): Promise<OAPENItemQueried[]> => {
const rawText = await get("items");
const transformed = rawText.map(
transformRawItemQueried
) as OAPENItemQueried[];
return transformed;
};
const getItemSingleRaw = async (uuid: string): Promise<OAPENItemQueried> => {
const rawText = await get(["items", uuid].map(encodeURIComponent).join("/"));
const transformed = transformRawItemQueried(rawText);
return transformed;
};
export const getItemSingleMetadata = async (
uuid: string
): Promise<RawMetadataItem[]> => {
const rawText = await get(
["items", uuid, "metadata"].map(encodeURIComponent).join("/")
);
return rawText as RawMetadataItem[];
};
const combineItemMetadata = (
item: OAPENItemQueried,
metadata: RawMetadataItem[]
): OAPENItemWithMetadata => {
return { ...item, metadata } as OAPENItemWithMetadata;
};
export const getItemWithMetadata = async (
uuid: string
): Promise<OAPENItemWithMetadata> => {
const [item, metadata] = await Promise.all([
getItemSingleRaw(uuid),
getItemSingleMetadata(uuid),
]);
return combineItemMetadata(item, metadata);
};

8
web/lib/oapen/query.ts Normal file
View File

@ -0,0 +1,8 @@
const ENDPOINT = "https://library.oapen.org/rest";
import axios from "axios";
export async function get(url = "") {
const post_url = [ENDPOINT, url].join("/");
const text = (await axios.get(post_url)).data;
return text;
}

5
web/next-env.d.ts vendored
View File

@ -1,2 +1,5 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

171
web/package-lock.json generated
View File

@ -8,11 +8,14 @@
"name": "oapen-suggestion-service",
"version": "0.1.0",
"dependencies": {
"@types/axios": "^0.14.0",
"axios": "^0.27.2",
"next": "12.3.1",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"@types/node": "18.8.1",
"@types/react": "18.0.21",
"eslint": "8.24.0",
"eslint-config-next": "12.3.1",
@ -368,12 +371,27 @@
"tslib": "^2.4.0"
}
},
"node_modules/@types/axios": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.14.0.tgz",
"integrity": "sha512-KqQnQbdYE54D7oa/UmYVMZKq7CO4l8DEENzOKc4aBRwxCXSlJXGz83flFx5L7AWrOQnmuN3kVsRdt+GZPPjiVQ==",
"deprecated": "This is a stub types definition for axios (https://github.com/mzabriskie/axios). axios provides its own type definitions, so you don't need @types/axios installed!",
"dependencies": {
"axios": "*"
}
},
"node_modules/@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
"dev": true
},
"node_modules/@types/node": {
"version": "18.8.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.1.tgz",
"integrity": "sha512-vuYaNuEIbOYLTLUAJh50ezEbvxrD43iby+lpUA2aa148Nh5kX/AVO/9m1Ahmbux2iU5uxJTNF9g2Y+31uml7RQ==",
"dev": true
},
"node_modules/@types/prop-types": {
"version": "15.7.5",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
@ -648,6 +666,11 @@
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
"dev": true
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/axe-core": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz",
@ -657,6 +680,15 @@
"node": ">=4"
}
},
"node_modules/axios": {
"version": "0.27.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
"dependencies": {
"follow-redirects": "^1.14.9",
"form-data": "^4.0.0"
}
},
"node_modules/axobject-query": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
@ -762,6 +794,17 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -844,6 +887,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@ -1507,6 +1558,38 @@
"integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
"dev": true
},
"node_modules/follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@ -2136,6 +2219,25 @@
"node": ">=8.6"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@ -3272,12 +3374,26 @@
"tslib": "^2.4.0"
}
},
"@types/axios": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.14.0.tgz",
"integrity": "sha512-KqQnQbdYE54D7oa/UmYVMZKq7CO4l8DEENzOKc4aBRwxCXSlJXGz83flFx5L7AWrOQnmuN3kVsRdt+GZPPjiVQ==",
"requires": {
"axios": "*"
}
},
"@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
"dev": true
},
"@types/node": {
"version": "18.8.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.1.tgz",
"integrity": "sha512-vuYaNuEIbOYLTLUAJh50ezEbvxrD43iby+lpUA2aa148Nh5kX/AVO/9m1Ahmbux2iU5uxJTNF9g2Y+31uml7RQ==",
"dev": true
},
"@types/prop-types": {
"version": "15.7.5",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
@ -3459,12 +3575,26 @@
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
"dev": true
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"axe-core": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz",
"integrity": "sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==",
"dev": true
},
"axios": {
"version": "0.27.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
"requires": {
"follow-redirects": "^1.14.9",
"form-data": "^4.0.0"
}
},
"axobject-query": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
@ -3542,6 +3672,14 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -3602,6 +3740,11 @@
"object-keys": "^1.1.1"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
"dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@ -4120,6 +4263,21 @@
"integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
"dev": true
},
"follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
},
"form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@ -4572,6 +4730,19 @@
"picomatch": "^2.3.1"
}
},
"mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
},
"mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"requires": {
"mime-db": "1.52.0"
}
},
"minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",

View File

@ -9,11 +9,14 @@
"lint": "next lint"
},
"dependencies": {
"@types/axios": "^0.14.0",
"axios": "^0.27.2",
"next": "12.3.1",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"@types/node": "18.8.1",
"@types/react": "18.0.21",
"eslint": "8.24.0",
"eslint-config-next": "12.3.1",

View File

@ -0,0 +1,43 @@
import type { GetStaticProps, GetStaticPaths } from "next";
import { OAPENItems } from "../../lib/oapen";
import type { OAPENItemWithMetadata } from "../../lib/oapen/OAPENTypes";
import { RenderItem } from "../../components/render/RenderItem";
interface SingleItemProps {
item: OAPENItemWithMetadata;
}
export default function ItemSingle({ item }: SingleItemProps) {
const name =
item.name || item.metadata.find(({ key }) => key == "grantor.name")?.value;
const type = item.metadata.find(({ key }) => key == "dc.type")?.value;
console.log({ item });
return (
<>
<RenderItem item={item} />
</>
);
}
// TODO update
export const getStaticPaths: GetStaticPaths = async () => {
return {
paths: [],
fallback: "blocking", // can also be true or 'blocking
};
};
export const getStaticProps: GetStaticProps<SingleItemProps> = async (
context
) => {
const item = await OAPENItems.getItemWithMetadata(context?.params?.uuid + "");
const data: SingleItemProps = {
item,
};
return {
props: {
...data,
},
};
};

38
web/pages/items/index.tsx Normal file
View File

@ -0,0 +1,38 @@
import type { GetStaticProps } from "next";
import { OAPENItems } from "../../lib/oapen";
import type { OAPENItemQueried } from "../../lib/oapen/OAPENTypes";
import Link from "next/link";
interface ManyProps {
many: OAPENItemQueried[];
}
export default function ItemMany({ many }: ManyProps) {
return (
<>
<h1>Listing</h1>
<ul>
{many.map((item) => (
<li key={item.uuid}>
<Link href={"/items/" + item.uuid}>
<a>{item.name || item.uuid}</a>
</Link>
</li>
))}
</ul>
</>
);
}
export const getStaticProps: GetStaticProps<ManyProps> = async (context) => {
const many = await OAPENItems.getItemsRaw();
const data: ManyProps = {
many,
};
return {
props: {
...data,
},
};
};

View File

@ -1,14 +1,18 @@
html,
body {
padding: 0;
margin: 0;
max-width: 900px;
margin-left: auto;
margin-right: auto;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
color: white;
background-color: black;
}
a {
color: inherit;
text-decoration: none;
/* text-decoration: none; */
}
* {

View File

@ -1,7 +1,11 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
@ -12,8 +16,15 @@
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
"jsx": "preserve",
"incremental": true
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
],
"exclude": [
"node_modules"
]
}