mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-05-01 17:53:59 +00:00
table structure tab WIP
This commit is contained in:
@@ -8,4 +8,11 @@ module.exports = {
|
|||||||
const res = await databaseConnections.sendRequest(opened, { msgtype: 'tableData', schemaName, pureName });
|
const res = await databaseConnections.sendRequest(opened, { msgtype: 'tableData', schemaName, pureName });
|
||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
tableInfo_meta: 'get',
|
||||||
|
async tableInfo({ conid, database, schemaName, pureName }) {
|
||||||
|
const opened = await databaseConnections.ensureOpened(conid, database);
|
||||||
|
const table = opened.structure.tables.find(x => x.pureName == pureName && x.schemaName == schemaName);
|
||||||
|
return table;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
const DatabaseAnalayser = require('../default/DatabaseAnalyser');
|
const DatabaseAnalayser = require('../default/DatabaseAnalyser');
|
||||||
|
|
||||||
@@ -27,13 +28,18 @@ class MsSqlAnalyser extends DatabaseAnalayser {
|
|||||||
}
|
}
|
||||||
async runAnalysis() {
|
async runAnalysis() {
|
||||||
const tables = await this.driver.query(this.pool, await this.createQuery('tables.sql'));
|
const tables = await this.driver.query(this.pool, await this.createQuery('tables.sql'));
|
||||||
// for (const table of tables) {
|
const columns = await this.driver.query(this.pool, await this.createQuery('columns.sql'));
|
||||||
// table.name = {
|
|
||||||
// schema: table.schemaName,
|
this.result.tables = tables.rows.map(table => ({
|
||||||
// name: table.tableName,
|
...table,
|
||||||
// };
|
columns: columns.rows
|
||||||
// }
|
.filter(col => col.objectId == table.objectId)
|
||||||
this.result.tables = tables.rows;
|
.map(({ isNullable, isIdentity, ...col }) => ({
|
||||||
|
...col,
|
||||||
|
notNull: isNullable != 'True',
|
||||||
|
autoIncrement: isIdentity == 'True',
|
||||||
|
})),
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
api/src/engines/mssql/columns.sql
Normal file
13
api/src/engines/mssql/columns.sql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
select c.name as columnName, t.name as dataType, c.object_id as objectId, c.is_identity as isIdentity,
|
||||||
|
c.max_length as maxLength, c.precision, c.scale, c.is_nullable as isNullable,
|
||||||
|
d.definition as defaultValue, d.name as defaultConstraint,
|
||||||
|
m.definition as computedExpression, m.is_persisted as isPersisted, c.column_id as columnId,
|
||||||
|
-- TODO only if version >= 2008
|
||||||
|
c.is_sparse as isSparse
|
||||||
|
from sys.columns c
|
||||||
|
inner join sys.types t on c.system_type_id = t.system_type_id and c.user_type_id = t.user_type_id
|
||||||
|
inner join sys.objects o on c.object_id = o.object_id
|
||||||
|
left join sys.default_constraints d on c.default_object_id = d.object_id
|
||||||
|
left join sys.computed_columns m on m.object_id = c.object_id and m.column_id = c.column_id
|
||||||
|
where o.type = 'U' and o.object_id =[OBJECT_ID_CONDITION]
|
||||||
|
order by c.column_id
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
select
|
select
|
||||||
o.name as pureName, s.name as schemaName, o.object_id,
|
o.name as pureName, s.name as schemaName, o.object_id as objectId,
|
||||||
o.create_date, o.modify_date
|
o.create_date, o.modify_date
|
||||||
from sys.tables o
|
from sys.tables o
|
||||||
inner join sys.schemas s on o.schema_id = s.schema_id
|
inner join sys.schemas s on o.schema_id = s.schema_id
|
||||||
|
|||||||
29
lib/src/dbinfo.ts
Normal file
29
lib/src/dbinfo.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { ChildProcess } from "child_process";
|
||||||
|
|
||||||
|
export interface NamedObjectInfo {
|
||||||
|
pureName: string;
|
||||||
|
schemaName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ColumnInfo {
|
||||||
|
columnName: string;
|
||||||
|
notNull: boolean;
|
||||||
|
autoIncrement: boolean;
|
||||||
|
dataType: string;
|
||||||
|
precision: number;
|
||||||
|
scale: number;
|
||||||
|
length: number;
|
||||||
|
computedExpression: string;
|
||||||
|
isPersisted: boolean;
|
||||||
|
isSparse: boolean;
|
||||||
|
defaultValue: string;
|
||||||
|
defaultConstraint: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TableInfo extends NamedObjectInfo {
|
||||||
|
columns: ColumnInfo[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DatabaseInfo {
|
||||||
|
tables: TableInfo[];
|
||||||
|
}
|
||||||
11
lib/src/engines.ts
Normal file
11
lib/src/engines.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { QueryResult } from "./query";
|
||||||
|
|
||||||
|
export interface EngineDriver {
|
||||||
|
connect({ server, port, user, password });
|
||||||
|
query(pool, sql: string): Promise<QueryResult>;
|
||||||
|
getVersion(pool): Promise<string>;
|
||||||
|
listDatabases(pool): Promise<{ name: string }[]>;
|
||||||
|
analyseFull(pool): Promise<void>;
|
||||||
|
analyseIncremental(pool): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,28 +1,5 @@
|
|||||||
import { ChildProcess } from "child_process";
|
import { ChildProcess } from "child_process";
|
||||||
|
import { DatabaseInfo } from "./dbinfo";
|
||||||
export interface QueryResult {
|
|
||||||
rows: any[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface EngineDriver {
|
|
||||||
connect({ server, port, user, password });
|
|
||||||
query(pool, sql: string): Promise<QueryResult>;
|
|
||||||
getVersion(pool): Promise<string>;
|
|
||||||
listDatabases(pool): Promise<{ name: string }[]>;
|
|
||||||
analyseFull(pool): Promise<void>;
|
|
||||||
analyseIncremental(pool): Promise<void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NamedObjectInfo {
|
|
||||||
pureName: string;
|
|
||||||
schemaName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TableInfo extends NamedObjectInfo {}
|
|
||||||
|
|
||||||
export interface DatabaseInfo {
|
|
||||||
tables: TableInfo[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface OpenedDatabaseConnection {
|
export interface OpenedDatabaseConnection {
|
||||||
conid: string;
|
conid: string;
|
||||||
@@ -31,6 +8,6 @@ export interface OpenedDatabaseConnection {
|
|||||||
subprocess: ChildProcess;
|
subprocess: ChildProcess;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sum(a: number, b: number) {
|
export * from "./engines";
|
||||||
return a + b;
|
export * from "./dbinfo";
|
||||||
}
|
export * from "./query";
|
||||||
|
|||||||
5
lib/src/query.ts
Normal file
5
lib/src/query.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { ChildProcess } from "child_process";
|
||||||
|
|
||||||
|
export interface QueryResult {
|
||||||
|
rows: any[];
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
"resize-observer-polyfill": "^1.5.1",
|
"resize-observer-polyfill": "^1.5.1",
|
||||||
"socket.io-client": "^2.3.0",
|
"socket.io-client": "^2.3.0",
|
||||||
"styled-components": "^4.4.1",
|
"styled-components": "^4.4.1",
|
||||||
|
"@dbgate/lib": "file:../lib",
|
||||||
"uuid": "^3.4.0"
|
"uuid": "^3.4.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ const IconWrap = styled.span`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export function AppObjectCore({ title, Icon, Menu, data, makeAppObj, onClick }) {
|
export function AppObjectCore({ title, Icon, Menu, data, makeAppObj, onClick }) {
|
||||||
|
const setOpenedTabs = useSetOpenedTabs();
|
||||||
|
|
||||||
const handleContextMenu = event => {
|
const handleContextMenu = event => {
|
||||||
if (!Menu) return;
|
if (!Menu) return;
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
showMenu(event.pageX, event.pageY, <Menu data={data} makeAppObj={makeAppObj} />);
|
showMenu(event.pageX, event.pageY, <Menu data={data} makeAppObj={makeAppObj} setOpenedTabs={setOpenedTabs} />);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
17
web/src/appobj/columnAppObject.js
Normal file
17
web/src/appobj/columnAppObject.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { TableIcon } from '../icons';
|
||||||
|
import { DropDownMenuItem } from '../modals/DropDownMenu';
|
||||||
|
import showModal from '../modals/showModal';
|
||||||
|
import ConnectionModal from '../modals/ConnectionModal';
|
||||||
|
import axios from '../utility/axios';
|
||||||
|
import { openNewTab } from '../utility/common';
|
||||||
|
import { useSetOpenedTabs } from '../utility/globalState';
|
||||||
|
|
||||||
|
/** @param columnProps {import('@dbgate/lib').ColumnInfo} */
|
||||||
|
export default function columnAppObject(columnProps, { setOpenedTabs }) {
|
||||||
|
const title = columnProps.columnName;
|
||||||
|
const key = title;
|
||||||
|
const Icon = TableIcon;
|
||||||
|
|
||||||
|
return { title, key, Icon };
|
||||||
|
}
|
||||||
@@ -5,18 +5,33 @@ import showModal from '../modals/showModal';
|
|||||||
import ConnectionModal from '../modals/ConnectionModal';
|
import ConnectionModal from '../modals/ConnectionModal';
|
||||||
import axios from '../utility/axios';
|
import axios from '../utility/axios';
|
||||||
import { openNewTab } from '../utility/common';
|
import { openNewTab } from '../utility/common';
|
||||||
|
import { useSetOpenedTabs } from '../utility/globalState';
|
||||||
|
|
||||||
function Menu({ data, makeAppObj }) {
|
function openTableDetail(setOpenedTabs, tabComponent, { schemaName, pureName, conid, database }) {
|
||||||
const handleEdit = () => {
|
openNewTab(setOpenedTabs, {
|
||||||
showModal(modalState => <ConnectionModal modalState={modalState} connection={data} />);
|
title: pureName,
|
||||||
|
icon: 'table2.svg',
|
||||||
|
tabComponent,
|
||||||
|
props: {
|
||||||
|
schemaName,
|
||||||
|
pureName,
|
||||||
|
conid,
|
||||||
|
database,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function Menu({ data, makeAppObj, setOpenedTabs }) {
|
||||||
|
const handleOpenData = () => {
|
||||||
|
openTableDetail(setOpenedTabs, 'TableDataTab', data);
|
||||||
};
|
};
|
||||||
const handleDelete = () => {
|
const handleOpenStructure = () => {
|
||||||
axios.post('connections/delete', data);
|
openTableDetail(setOpenedTabs, 'TableStructureTab', data);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DropDownMenuItem onClick={handleEdit}>Edit</DropDownMenuItem>
|
<DropDownMenuItem onClick={handleOpenData}>Open data</DropDownMenuItem>
|
||||||
<DropDownMenuItem onClick={handleDelete}>Delete</DropDownMenuItem>
|
<DropDownMenuItem onClick={handleOpenStructure}>Open structure</DropDownMenuItem>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -26,16 +41,11 @@ export default function tableAppObject({ conid, database, pureName, schemaName }
|
|||||||
const key = title;
|
const key = title;
|
||||||
const Icon = TableIcon;
|
const Icon = TableIcon;
|
||||||
const onClick = ({ schemaName, pureName }) => {
|
const onClick = ({ schemaName, pureName }) => {
|
||||||
openNewTab(setOpenedTabs, {
|
openTableDetail(setOpenedTabs, 'TableDataTab', {
|
||||||
title: pureName,
|
schemaName,
|
||||||
icon: 'table2.svg',
|
pureName,
|
||||||
tabComponent: 'TableDataTab',
|
conid,
|
||||||
props: {
|
database,
|
||||||
schemaName,
|
|
||||||
pureName,
|
|
||||||
conid,
|
|
||||||
database,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
body {
|
body {
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
font-family: -apple-system,BlinkMacSystemFont,Segoe WPC,Segoe UI,HelveticaNeue-Light,Ubuntu,Droid Sans,sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
/* font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||||
sans-serif;
|
sans-serif;
|
||||||
|
*/
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|||||||
78
web/src/tabs/TableStructureTab.js
Normal file
78
web/src/tabs/TableStructureTab.js
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import useFetch from '../utility/useFetch';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import theme from '../theme';
|
||||||
|
import ObjectListControl from '../utility/ObjectListControl';
|
||||||
|
import { TableColumn } from '../utility/TableControl';
|
||||||
|
|
||||||
|
const WhitePage = styled.div`
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: white;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default function TableStructureTab({ conid, database, schemaName, pureName }) {
|
||||||
|
/** @type {import('@dbgate/lib').TableInfo} */
|
||||||
|
const tableInfo = useFetch({
|
||||||
|
url: 'tables/table-info',
|
||||||
|
params: { conid, database, schemaName, pureName },
|
||||||
|
});
|
||||||
|
if (!tableInfo) return null;
|
||||||
|
return (
|
||||||
|
<WhitePage>
|
||||||
|
<ObjectListControl
|
||||||
|
collection={tableInfo.columns.map((x, index) => ({ ...x, ordinal: index + 1 }))}
|
||||||
|
title="Columns"
|
||||||
|
>
|
||||||
|
<TableColumn
|
||||||
|
fieldName="notNull"
|
||||||
|
header="Not NULL"
|
||||||
|
sortable={true}
|
||||||
|
formatter={row => (row.notNull ? 'YES' : 'NO')}
|
||||||
|
/>
|
||||||
|
<TableColumn fieldName="dataType" header="Data Type" sortable={true} />
|
||||||
|
<TableColumn fieldName="defaultValue" header="Default value" sortable={true} />
|
||||||
|
<TableColumn
|
||||||
|
fieldName="isSparse"
|
||||||
|
header="Is Sparse"
|
||||||
|
sortable={true}
|
||||||
|
formatter={row => (row.isSparse ? 'YES' : 'NO')}
|
||||||
|
/>
|
||||||
|
<TableColumn fieldName="computedExpression" header="Computed Expression" sortable={true} />
|
||||||
|
<TableColumn
|
||||||
|
fieldName="isPersisted"
|
||||||
|
header="Is Persisted"
|
||||||
|
sortable={true}
|
||||||
|
formatter={row => (row.isPersisted ? 'YES' : 'NO')}
|
||||||
|
/>
|
||||||
|
{/* {_.includes(dbCaps.columnListOptionalColumns, 'referencedTableNamesFormatted') && (
|
||||||
|
<TableColumn fieldName="referencedTableNamesFormatted" header="References" sortable={true} />
|
||||||
|
)}
|
||||||
|
<TableColumn
|
||||||
|
fieldName="actions"
|
||||||
|
header=""
|
||||||
|
formatter={row => (
|
||||||
|
<span>
|
||||||
|
<Link
|
||||||
|
linkElementId={encodeHtmlId(`button_delete_column_${row.column.name}`)}
|
||||||
|
onClick={() => this.deleteColumn(row)}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</Link>{' '}
|
||||||
|
|{' '}
|
||||||
|
<Link
|
||||||
|
linkElementId={encodeHtmlId(`button_edit_column__${row.column.name}`)}
|
||||||
|
onClick={() => this.editColumn(row)}
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</Link>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
/> */}
|
||||||
|
</ObjectListControl>
|
||||||
|
</WhitePage>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
import TableDataTab from './TableDataTab';
|
import TableDataTab from './TableDataTab';
|
||||||
|
import TableStructureTab from './TableStructureTab';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
TableDataTab,
|
TableDataTab,
|
||||||
|
TableStructureTab,
|
||||||
};
|
};
|
||||||
|
|||||||
41
web/src/utility/ObjectListControl.js
Normal file
41
web/src/utility/ObjectListControl.js
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import useFetch from '../utility/useFetch';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import theme from '../theme';
|
||||||
|
import TableControl from './TableControl';
|
||||||
|
|
||||||
|
const ObjectListWrapper = styled.div`
|
||||||
|
margin-bottom: 20px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ObjectListHeader = styled.div`
|
||||||
|
background-color: #ebedef;
|
||||||
|
padding: 5px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ObjectListHeaderTitle = styled.span`
|
||||||
|
font-weight: bold;
|
||||||
|
margin-left: 5px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ObjectListBody = styled.div`
|
||||||
|
margin: 20px;
|
||||||
|
// margin-left: 20px;
|
||||||
|
// margin-right: 20px;
|
||||||
|
// margin-top: 3px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default function ObjectListControl({ collection = [], title, showIfEmpty = false, children }) {
|
||||||
|
if (collection.length == 0 && !showIfEmpty) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ObjectListWrapper>
|
||||||
|
<ObjectListHeader>
|
||||||
|
<ObjectListHeaderTitle>{title}</ObjectListHeaderTitle>
|
||||||
|
</ObjectListHeader>
|
||||||
|
<ObjectListBody>
|
||||||
|
<TableControl rows={collection}>{children}</TableControl>
|
||||||
|
</ObjectListBody>
|
||||||
|
</ObjectListWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
59
web/src/utility/TableControl.js
Normal file
59
web/src/utility/TableControl.js
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import useFetch from '../utility/useFetch';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import theme from '../theme';
|
||||||
|
|
||||||
|
const Table = styled.table`
|
||||||
|
border-collapse: collapse;
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
const TableHead = styled.thead``;
|
||||||
|
const TableBody = styled.tbody``;
|
||||||
|
const TableHeaderRow = styled.tr``;
|
||||||
|
const TableBodyRow = styled.tr``;
|
||||||
|
const TableHeaderCell = styled.td`
|
||||||
|
border: 1px solid #e8eef4;
|
||||||
|
background-color: #e8eef4;
|
||||||
|
padding: 5px;
|
||||||
|
`;
|
||||||
|
const TableBodyCell = styled.td`
|
||||||
|
border: 1px solid #e8eef4;
|
||||||
|
padding: 5px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export function TableColumn({ fieldName, header, sortable, formatter = undefined }) {
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function format(row, col) {
|
||||||
|
const { formatter, fieldName } = col;
|
||||||
|
if (formatter) return formatter(row);
|
||||||
|
return row[fieldName];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function TableControl({ rows = [], children }) {
|
||||||
|
const columns = (children instanceof Array ? children : [children])
|
||||||
|
.filter(child => child != null)
|
||||||
|
.map(child => child.props);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Table>
|
||||||
|
<TableHead>
|
||||||
|
<TableHeaderRow>
|
||||||
|
{columns.map(x => (
|
||||||
|
<TableHeaderCell key={x.fieldName}>{x.header}</TableHeaderCell>
|
||||||
|
))}
|
||||||
|
</TableHeaderRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{rows.map((row, index) => (
|
||||||
|
<TableBodyRow key={index}>
|
||||||
|
{columns.map(col => (
|
||||||
|
<TableBodyCell key={col.fieldName}>{format(row, col)}</TableBodyCell>
|
||||||
|
))}
|
||||||
|
</TableBodyRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -15,12 +15,12 @@
|
|||||||
"lib": [
|
"lib": [
|
||||||
"dom",
|
"dom",
|
||||||
"dom.iterable",
|
"dom.iterable",
|
||||||
"esnext"
|
"esnext",
|
||||||
],
|
],
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true
|
"isolatedModules": true,
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src"
|
"src"
|
||||||
|
|||||||
Reference in New Issue
Block a user