[chore] Convert some settings / admin panel JS to TypeScript (#2247)

* initial conversion of STUFF to typescript

* more stuff

* update babel deps, include commonjs transform

* update bundler & eslint configuration

* eslint --fix

* upgrade deps

* update docs, build stuff, peripheral stuff

---------

Co-authored-by: f0x <f0x@cthu.lu>
This commit is contained in:
tobi 2023-10-05 16:06:19 +02:00 committed by GitHub
parent 6e508830e1
commit d173fcdfa3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
84 changed files with 2365 additions and 1621 deletions

View File

@ -53,8 +53,7 @@ steps:
- name: yarn_cache
path: /tmp/cache
commands:
- cd web/source
- yarn --frozen-lockfile --cache-folder /tmp/cache
- yarn --cwd ./web/source install --frozen-lockfile --cache-folder /tmp/cache
- name: web-lint
image: node:18-alpine
@ -65,8 +64,7 @@ steps:
depends_on:
- web-setup
commands:
- cd web/source
- yarn run lint
- yarn --cwd ./web/source lint
- name: web-build
image: node:18-alpine
@ -77,8 +75,7 @@ steps:
depends_on:
- web-setup
commands:
- cd web/source
- yarn run build
- yarn --cwd ./web/source build
- name: snapshot
image: superseriousbusiness/gotosocial-drone-build:0.3.0 # https://github.com/superseriousbusiness/gotosocial-drone-build
@ -194,6 +191,6 @@ steps:
---
kind: signature
hmac: 74653d67ed44ceefb7e19d6125d4a457e6308b5ef627df6325d72a0cc7d7cc0a
hmac: c3efbd528a76016562f88ae435141cfb5fd6d4d07b6ad2a24ecc23cb529cc1c6
...

View File

@ -6,9 +6,9 @@ before:
# generate the swagger.yaml file using go-swagger and bundle it into the assets directory
- swagger generate spec --scan-models --exclude-deps -o web/assets/swagger.yaml
- sed -i "s/REPLACE_ME/{{ incpatch .Version }}/" web/assets/swagger.yaml
# bundle web assets
- yarn install --cwd web/source
- scripts/bundle.sh
# Install web deps + bundle web assets
- yarn --cwd ./web/source install
- yarn --cwd ./web/source build
builds:
# https://goreleaser.com/customization/build/
-

View File

@ -226,31 +226,44 @@ To bundle changes, you need [Node.js](https://nodejs.org/en/download/) and [Yarn
Using [NVM](https://github.com/nvm-sh/nvm) is one convenient way to install them which also supports managing different Node versions.
To install Yarn dependencies:
To install frontend dependencies:
```bash
yarn install --cwd web/source
yarn --cwd web/source
```
To recompile bundles:
To recompile frontend bundles into `web/assets/dist`:
```bash
node web/source
yarn --cwd web/source build
```
#### Live Reloading
For a more convenient development environment, you can run a livereloading version of the bundler alongside the [testrig](#testing).
Open two terminals, first start the testrig on port 8081:
First build the GtS binary with DEBUG=1 to enable the testrig:
``` bash
GTS_PORT=8081 go run ./cmd/gotosocial testrig start
DEBUG=1 ./scripts/build.sh
```
Now open two terminals.
In the first terminal, run the testrig on port 8081, using the binary you just built:
```bash
DEBUG=1 GTS_PORT=8081 ./gotosocial testrig start
```
Then start the bundler, which will run on port 8080, and proxy requests to the testrig instance where needed.
``` bash
NODE_ENV=development node web/source
NODE_ENV=development yarn --cwd ./web/source dev
```
You can then log in to the GoToSocial settings panel at `http://localhost:8080/settings` and see your changes reflected in real time as the dev bundler reloads.
The livereloading bundler *will not* change the bundled assets in `dist/`, so once you are finished with changes and want to deploy it somewhere, you have to run `node web/source` to generate production-ready bundles.
### Project Structure

View File

@ -12,12 +12,12 @@ WORKDIR /go/src/github.com/superseriousbusiness/gotosocial
RUN swagger generate spec -o /go/src/github.com/superseriousbusiness/gotosocial/swagger.yaml --scan-models
# stage 2: generate the web/assets/dist bundles
FROM --platform=${BUILDPLATFORM} node:16.19.1-alpine3.17 AS bundler
FROM --platform=${BUILDPLATFORM} node:18-alpine AS bundler
COPY web web
RUN yarn install --cwd web/source && \
BUDO_BUILD=1 node web/source && \
rm -r web/source
RUN yarn --cwd ./web/source install && \
yarn --cwd ./web/source build && \
rm -rf ./web/source
# stage 3: build the executor container
FROM --platform=${TARGETPLATFORM} alpine:3.17.2 as executor

View File

@ -1,8 +0,0 @@
#!/bin/sh
# this script is really just here because GoReleaser doesn't let
# you set env vars in your 'before' commands in the free version
set -eu
BUDO_BUILD=1 node web/source

View File

@ -17,13 +17,15 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
module.exports = {
"extends": ["@joepie91/eslint-config/react"],
"plugins": ["license-header"],
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint", "license-header"],
"rules": {
"license-header/header": ["error", __dirname + "/.license-header.js"],
"no-console": 'error'
},
"parserOptions": {
"sourceType": "module"
}
};

View File

@ -1,2 +1,5 @@
node_modules
public/bundle.*
# Built/Typescript-compiled settings files.
settings-js

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const Photoswipe = require("photoswipe/dist/umd/photoswipe.umd.min.js");
const PhotoswipeLightbox = require("photoswipe/dist/umd/photoswipe-lightbox.umd.min.js");
const PhotoswipeCaptionPlugin = require("photoswipe-dynamic-caption-plugin").default;

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const skulk = require("skulk");
const fs = require("fs");
const path = require("path");
@ -70,10 +68,17 @@ skulk({
entryFile: "settings",
outputFile: "settings.js",
prodCfg: prodCfg,
plugin: [
// Additional settings for TS are passed from tsconfig.json.
// See: https://github.com/TypeStrong/tsify#tsconfigjson
["tsify"]
],
transform: [
// tsify is called before babelify, so we're just babelifying
// commonjs here, no need for the typescript preset.
["babelify", {
global: true,
ignore: [/node_modules\/(?!nanoid)/]
ignore: [/node_modules\/(?!nanoid)/],
}]
],
presets: [

View File

@ -6,7 +6,7 @@
"author": "f0x",
"license": "AGPL-3.0",
"scripts": {
"lint": "eslint . --ext .js,.jsx",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
"build": "node index.js",
"dev": "NODE_ENV=development node index.js"
},
@ -29,21 +29,25 @@
"psl": "^1.9.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-redux": "^8.0.4",
"react-redux": "^8.1.3",
"redux": "^4.2.0",
"redux-persist": "^6.0.0",
"skulk": "^0.0.6",
"skulk": "^0.0.8-fix",
"split-filter-n": "^1.1.3",
"syncpipe": "^1.0.0",
"wouter": "^2.8.0-alpha.2"
},
"devDependencies": {
"@babel/core": "^7.19.6",
"@babel/preset-env": "^7.19.4",
"@babel/preset-react": "^7.18.6",
"@babel/core": "^7.23.0",
"@babel/preset-env": "^7.22.20",
"@babel/preset-react": "^7.22.15",
"@babel/preset-typescript": "^7.23.0",
"@browserify/envify": "^6.0.0",
"@browserify/uglifyify": "^6.0.0",
"@joepie91/eslint-config": "^1.1.1",
"@types/react-dom": "^18.2.8",
"@typescript-eslint/eslint-plugin": "^6.7.4",
"@typescript-eslint/parser": "^6.7.4",
"autoprefixer": "^10.4.13",
"babelify": "^10.0.0",
"css-extract": "^2.0.0",
@ -56,6 +60,10 @@
"postcss": "^8.4.18",
"postcss-custom-prop-vars": "^0.0.5",
"postcss-import": "^15.0.0",
"postcss-nested": "^6.0.0"
"postcss-nested": "^6.0.0",
"source-map-loader": "^4.0.1",
"ts-loader": "^9.4.4",
"tsify": "^5.0.4",
"typescript": "^5.2.2"
}
}

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { useRoute, Redirect } = require("wouter");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { Switch, Route, Link } = require("wouter");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const query = require("../../../lib/query");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const ExpireRemote = require("./expireremote");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const query = require("../../../lib/query");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const Cleanup = require("./cleanup");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const splitFilterN = require("split-filter-n");
const syncpipe = require('syncpipe');

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { useRoute, Link, Redirect } = require("wouter");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { Switch, Route } = require("wouter");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const query = require("../../../lib/query");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { Link } = require("wouter");
const syncpipe = require("syncpipe");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const query = require("../../../lib/query");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const ParseFromToot = require("./parse-from-toot");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const query = require("../../../lib/query");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { useRoute, Redirect, useLocation } = require("wouter");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
module.exports = function ExportFormatTable() {

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const query = require("../../../lib/query");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { Switch, Route, Redirect, useLocation } = require("wouter");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const query = require("../../../lib/query");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { Switch, Route } = require("wouter");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { Link, useLocation } = require("wouter");
const { matchSorter } = require("match-sorter");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { useRoute, Redirect } = require("wouter");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { Link, Switch, Route } = require("wouter");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { Link } = require("wouter");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const query = require("../../lib/query");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { Switch, Route, Link, Redirect, useRoute } = require("wouter");

View File

@ -17,23 +17,25 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
import { useVerifyCredentialsQuery } from "../../lib/query/oauth";
import { store } from "../../redux/store";
const React = require("react");
const Redux = require("react-redux");
import React from "react";
const query = require("../../lib/query");
import Login from "./login";
import Loading from "../loading";
import { Error } from "../error";
const Login = require("./login");
const Loading = require("../loading");
const { Error } = require("../error");
export function Authorization({ App }) {
const { loginState, expectingRedirect } = store.getState().oauth;
const skip = (loginState == "none" || loginState == "logout" || expectingRedirect);
module.exports = function Authorization({ App }) {
const { loginState, expectingRedirect } = Redux.useSelector((state) => state.oauth);
const { isLoading, isSuccess, data: account, error } = query.useVerifyCredentialsQuery(undefined, {
skip: loginState == "none" || loginState == "logout" || expectingRedirect
});
const {
isLoading,
isSuccess,
data: account,
error,
} = useVerifyCredentialsQuery(null, { skip: skip });
let showLogin = true;
let content = null;
@ -73,4 +75,4 @@ module.exports = function Authorization({ App }) {
</section>
);
}
};
}

View File

@ -17,18 +17,16 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
import React from "react";
const React = require("react");
import { useAuthorizeFlowMutation } from "../../lib/query/oauth";
import { useTextInput, useValue } from "../../lib/form";
import useFormSubmit from "../../lib/form/submit";
import { TextInput } from "../form/inputs";
import MutationButton from "../form/mutation-button";
import Loading from "../loading";
const query = require("../../lib/query");
const { useTextInput, useValue } = require("../../lib/form");
const useFormSubmit = require("../../lib/form/submit");
const { TextInput } = require("../form/inputs");
const MutationButton = require("../form/mutation-button");
const Loading = require("../loading");
module.exports = function Login({ }) {
export default function Login({ }) {
const form = {
instance: useTextInput("instance", {
defaultValue: window.location.origin
@ -38,8 +36,11 @@ module.exports = function Login({ }) {
const [formSubmit, result] = useFormSubmit(
form,
query.useAuthorizeFlowMutation(),
{ changedOnly: false }
useAuthorizeFlowMutation(),
{
changedOnly: false,
onFinish: undefined,
}
);
if (result.isLoading) {
@ -63,7 +64,11 @@ module.exports = function Login({ }) {
label="Instance"
name="instance"
/>
<MutationButton label="Login" result={result} />
<MutationButton
label="Login"
result={result}
disabled={false}
/>
</form>
);
};
}

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { Link } = require("wouter");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
module.exports = function CheckList({ field, header = "All", EntryComponent, getExtraProps }) {

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const {

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
function ErrorFallback({ error, resetErrorBoundary }) {

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
module.exports = function FakeProfile({ avatar, header, display_name, username, role }) {

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const query = require("../lib/query");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
function TextInput({ label, field, ...inputProps }) {

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { Error } = require("../error");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const langs = require("langs");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
module.exports = function Loading() {

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const query = require("../lib/query");

View File

@ -17,17 +17,15 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const ReactDom = require("react-dom/client");
const { Provider } = require("react-redux");
const { PersistGate } = require("redux-persist/integration/react");
const { store, persistor } = require("./redux");
const { store, persistor } = require("./redux/store");
const { createNavigation, Menu, Item } = require("./lib/navigation");
const AuthorizationGate = require("./components/authorization");
const { Authorization } = require("./components/authorization");
const Loading = require("./components/loading");
const UserLogoutCard = require("./components/user-logout-card");
const { RoleContext } = require("./lib/navigation/util");
@ -90,7 +88,7 @@ function Main() {
return (
<Provider store={store}>
<PersistGate loading={<section><Loading /></section>} persistor={persistor}>
<AuthorizationGate App={App} />
<Authorization App={App} />
</PersistGate>
</Provider>
);

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const isValidDomain = require("is-valid-domain");
const psl = require("psl");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const _default = false;

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const syncpipe = require("syncpipe");
const { createSlice } = require("@reduxjs/toolkit");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { useComboboxState } = require("ariakit/combobox");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const FormContext = React.createContext({});

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const getFormMutations = require("./get-form-mutations");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const prettierBytes = require("prettier-bytes");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { Error } = require("../../components/error");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const syncpipe = require("syncpipe");
module.exports = function getFormMutations(form, { changedOnly }) {

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const getByDot = require("get-by-dot").default;

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const _default = "";

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const Promise = require("bluebird");
const React = require("react");
const getFormMutations = require("./get-form-mutations");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const _default = "";

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { Link, Route, Redirect, Switch, useLocation, useRouter } = require("wouter");
const syncpipe = require("syncpipe");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const { nanoid } = require("nanoid");
const { Redirect } = require("wouter");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const RoleContext = React.createContext([]);
const BaseUrlContext = React.createContext(null);

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const Promise = require("bluebird");
const { unwrapRes } = require("../lib");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const Promise = require("bluebird");
const fileDownload = require("js-file-download");
const csv = require("papaparse");

View File

@ -17,15 +17,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const {
replaceCacheOnMutation,
removeFromCacheOnMutation,
domainListToObject,
idListToObject
} = require("../lib");
const base = require("../base");
const { gtsApi } = require("../gts-api");
const endpoints = (build) => ({
updateInstance: build.mutation({
@ -164,4 +162,4 @@ const endpoints = (build) => ({
...require("./reports")(build)
});
module.exports = base.injectEndpoints({ endpoints });
module.exports = gtsApi.injectEndpoints({ endpoints });

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
module.exports = (build) => ({
listReports: build.query({
query: (params = {}) => ({

View File

@ -1,70 +0,0 @@
/*
GoToSocial
Copyright (C) GoToSocial Authors admin@gotosocial.org
SPDX-License-Identifier: AGPL-3.0-or-later
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const { createApi, fetchBaseQuery } = require("@reduxjs/toolkit/query/react");
const { serialize: serializeForm } = require("object-to-formdata");
function instanceBasedQuery(args, api, extraOptions) {
const state = api.getState();
const { instance, token } = state.oauth;
if (args.baseUrl == undefined) {
args.baseUrl = instance;
}
if (args.discardEmpty) {
if (args.body == undefined || Object.keys(args.body).length == 0) {
return { data: null };
}
delete args.discardEmpty;
}
if (args.asForm) {
delete args.asForm;
args.body = serializeForm(args.body, {
indices: true, // Array indices, for profile fields
});
}
return fetchBaseQuery({
baseUrl: args.baseUrl,
prepareHeaders: (headers) => {
if (token != undefined) {
headers.set('Authorization', token);
}
headers.set("Accept", "application/json");
return headers;
},
})(args, api, extraOptions);
}
module.exports = createApi({
reducerPath: "api",
baseQuery: instanceBasedQuery,
tagTypes: ["Auth", "Emoji", "Reports", "Account", "InstanceRules"],
endpoints: (build) => ({
instance: build.query({
query: () => ({
url: `/api/v1/instance`
})
})
})
});

View File

@ -0,0 +1,149 @@
/*
GoToSocial
Copyright (C) GoToSocial Authors admin@gotosocial.org
SPDX-License-Identifier: AGPL-3.0-or-later
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import type {
BaseQueryFn,
FetchArgs,
FetchBaseQueryError,
} from '@reduxjs/toolkit/query/react';
import { serialize as serializeForm } from "object-to-formdata";
import type { RootState } from '../../redux/store';
/**
* GTSFetchArgs extends standard FetchArgs used by
* RTK Query with a couple helpers of our own.
*/
export interface GTSFetchArgs extends FetchArgs {
/**
* If provided, will be used as base URL. Else,
* will fall back to authorized instance as baseUrl.
*/
baseUrl?: string;
/**
* If true, and no args.body is set, or args.body is empty,
* then a null response will be returned from the API call.
*/
discardEmpty?: boolean;
/**
* If true, then args.body will be serialized
* as FormData before submission.
*/
asForm?: boolean;
}
/**
* gtsBaseQuery wraps the redux toolkit fetchBaseQuery with some helper functionality.
*
* For an explainer of what's happening in this function, see:
* - https://redux-toolkit.js.org/rtk-query/usage/customizing-queries#customizing-queries-with-basequery
* - https://redux-toolkit.js.org/rtk-query/usage/customizing-queries#constructing-a-dynamic-base-url-using-redux-state
*
* @param args
* @param api
* @param extraOptions
* @returns
*/
const gtsBaseQuery: BaseQueryFn<
string | GTSFetchArgs,
any,
FetchBaseQueryError
> = async (args, api, extraOptions) => {
// Retrieve state at the moment
// this function was called.
const state = api.getState() as RootState;
const { instanceUrl, token } = state.oauth;
// Derive baseUrl dynamically.
let baseUrl: string;
// Check if simple string baseUrl provided
// as args, or if more complex args provided.
if (typeof args === "string") {
baseUrl = args;
} else {
if (args.baseUrl != undefined) {
baseUrl = args.baseUrl;
} else {
baseUrl = instanceUrl;
}
if (args.discardEmpty) {
if (args.body == undefined || Object.keys(args.body).length == 0) {
return { data: null };
}
}
if (args.asForm) {
args.body = serializeForm(args.body, {
// Array indices, for profile fields.
indices: true,
});
}
// Delete any of our extended arguments
// to avoid confusing fetchBaseQuery.
delete args.baseUrl;
delete args.discardEmpty;
delete args.asForm;
}
if (!baseUrl) {
return {
error: {
status: 400,
statusText: 'Bad Request',
data: {"error":"No baseUrl set for request"},
},
};
}
return fetchBaseQuery({
baseUrl: baseUrl,
prepareHeaders: (headers) => {
if (token != undefined) {
headers.set('Authorization', token);
}
headers.set("Accept", "application/json");
return headers;
},
})(args, api, extraOptions);
};
export const gtsApi = createApi({
reducerPath: "api",
baseQuery: gtsBaseQuery,
tagTypes: [
"Auth",
"Emoji",
"Reports",
"Account",
"InstanceRules",
],
endpoints: (builder) => ({
instance: builder.query<any, void>({
query: () => ({
url: `/api/v1/instance`
})
})
})
});
export const { useInstanceQuery } = gtsApi;

View File

@ -17,11 +17,9 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
module.exports = {
...require("./base"),
...require("./gts-api"),
...require("./oauth"),
...require("./user"),
...require("./admin")
};
};

View File

@ -17,10 +17,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const syncpipe = require("syncpipe");
const base = require("./base");
const { gtsApi } = require("./gts-api");
module.exports = {
unwrapRes(res) {
@ -70,7 +68,7 @@ function makeCacheMutation(action) {
return {
onQueryStarted: (_, { dispatch, queryFulfilled }) => {
queryFulfilled.then(({ data: newData }) => {
dispatch(base.util.updateQueryData(queryName, arg, (draft) => {
dispatch(gtsApi.util.updateQueryData(queryName, arg, (draft) => {
if (findKey != undefined) {
key = findKey(draft, newData);
}

View File

@ -1,160 +0,0 @@
/*
GoToSocial
Copyright (C) GoToSocial Authors admin@gotosocial.org
SPDX-License-Identifier: AGPL-3.0-or-later
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const Promise = require("bluebird");
const base = require("./base");
const { unwrapRes } = require("./lib");
const oauth = require("../../redux/oauth").actions;
function getSettingsURL() {
/* needed in case the settings interface isn't hosted at /settings but
some subpath like /gotosocial/settings. Other parts of the code don't
take this into account yet so mostly future-proofing.
Also drops anything past /settings/, because authorization urls that are too long
get rejected by GTS.
*/
let [pre, _past] = window.location.pathname.split("/settings");
return `${window.location.origin}${pre}/settings`;
}
const SETTINGS_URL = getSettingsURL();
const endpoints = (build) => ({
verifyCredentials: build.query({
providesTags: (_res, error) =>
error == undefined
? ["Auth"]
: [],
queryFn: (_arg, api, _extraOpts, baseQuery) => {
const state = api.getState();
return Promise.try(() => {
// Process callback code first, if available
if (state.oauth.loginState == "callback") {
let urlParams = new URLSearchParams(window.location.search);
let code = urlParams.get("code");
if (code == undefined) {
throw {
message: "Waiting for callback, but no ?code= provided in url."
};
} else {
let app = state.oauth.registration;
if (app == undefined || app.client_id == undefined) {
throw {
message: "No stored registration data, can't finish login flow."
};
}
return baseQuery({
method: "POST",
url: "/oauth/token",
body: {
client_id: app.client_id,
client_secret: app.client_secret,
redirect_uri: SETTINGS_URL,
grant_type: "authorization_code",
code: code
}
}).then(unwrapRes).then((token) => {
// remove ?code= from url
window.history.replaceState({}, document.title, window.location.pathname);
api.dispatch(oauth.setToken(token));
});
}
}
}).then(() => {
return baseQuery({
url: `/api/v1/accounts/verify_credentials`
});
}).catch((e) => {
return { error: e };
});
}
}),
authorizeFlow: build.mutation({
queryFn: (formData, api, _extraOpts, baseQuery) => {
let instance;
const state = api.getState();
return Promise.try(() => {
if (!formData.instance.startsWith("http")) {
formData.instance = `https://${formData.instance}`;
}
instance = new URL(formData.instance).origin;
const stored = state.oauth.instance;
if (stored?.instance == instance && stored.registration) {
return stored.registration;
}
return baseQuery({
method: "POST",
baseUrl: instance,
url: "/api/v1/apps",
body: {
client_name: "GoToSocial Settings",
scopes: formData.scopes,
redirect_uris: SETTINGS_URL,
website: SETTINGS_URL
}
}).then(unwrapRes).then((app) => {
app.scopes = formData.scopes;
api.dispatch(oauth.authorize({
instance: instance,
registration: app,
loginState: "callback",
expectingRedirect: true
}));
return app;
});
}).then((app) => {
let url = new URL(instance);
url.pathname = "/oauth/authorize";
url.searchParams.set("client_id", app.client_id);
url.searchParams.set("redirect_uri", SETTINGS_URL);
url.searchParams.set("response_type", "code");
url.searchParams.set("scope", app.scopes);
let redirectURL = url.toString();
window.location.assign(redirectURL);
return { data: null };
}).catch((e) => {
return { error: e };
});
},
}),
logout: build.mutation({
queryFn: (_arg, api) => {
api.dispatch(oauth.remove());
return { data: null };
},
invalidatesTags: ["Auth"]
})
});
module.exports = base.injectEndpoints({ endpoints });

View File

@ -0,0 +1,204 @@
/*
GoToSocial
Copyright (C) GoToSocial Authors admin@gotosocial.org
SPDX-License-Identifier: AGPL-3.0-or-later
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import type { FetchBaseQueryError } from '@reduxjs/toolkit/query';
import { gtsApi } from "../gts-api";
import {
setToken as oauthSetToken,
remove as oauthRemove,
authorize as oauthAuthorize,
} from "../../../redux/oauth";
import { RootState } from '../../../redux/store';
export interface OauthTokenRequestBody {
client_id: string;
client_secret: string;
redirect_uri: string;
grant_type: string;
code: string;
}
function getSettingsURL() {
/*
needed in case the settings interface isn't hosted at /settings but
some subpath like /gotosocial/settings. Other parts of the code don't
take this into account yet so mostly future-proofing.
Also drops anything past /settings/, because authorization urls that are too long
get rejected by GTS.
*/
let [pre, _past] = window.location.pathname.split("/settings");
return `${window.location.origin}${pre}/settings`;
}
const SETTINGS_URL = (getSettingsURL());
// Couple auth functions here require multiple requests as
// part of an OAuth token 'flow'. To keep things simple for
// callers of these query functions, the multiple requests
// are chained within one query.
//
// https://redux-toolkit.js.org/rtk-query/usage/customizing-queries#performing-multiple-requests-with-a-single-query
const extended = gtsApi.injectEndpoints({
endpoints: (builder) => ({
verifyCredentials: builder.query<any, void>({
providesTags: (_res, error) =>
error == undefined ? ["Auth"] : [],
async queryFn(_arg, api, _extraOpts, fetchWithBQ) {
const state = api.getState() as RootState;
const oauthState = state.oauth;
// If we're not in the middle of an auth/callback,
// we may already have an auth token, so just
// return a standard verify_credentials query.
if (oauthState.loginState != 'callback') {
return fetchWithBQ({
url: `/api/v1/accounts/verify_credentials`
});
}
// We're in the middle of an auth/callback flow.
// Try to retrieve callback code from URL query.
let urlParams = new URLSearchParams(window.location.search);
let code = urlParams.get("code");
if (code == undefined) {
return {
error: {
status: 400,
statusText: 'Bad Request',
data: {"error":"Waiting for callback, but no ?code= provided in url."},
},
};
}
// Retrieve app with which the
// callback code was generated.
let app = oauthState.app;
if (app == undefined || app.client_id == undefined) {
return {
error: {
status: 400,
statusText: 'Bad Request',
data: {"error":"No stored app registration data, can't finish login flow."},
},
};
}
// Use the provided code and app
// secret to request an auth token.
const tokenReqBody: OauthTokenRequestBody = {
client_id: app.client_id,
client_secret: app.client_secret,
redirect_uri: SETTINGS_URL,
grant_type: "authorization_code",
code: code
};
const tokenResult = await fetchWithBQ({
method: "POST",
url: "/oauth/token",
body: tokenReqBody,
});
if (tokenResult.error) {
return { error: tokenResult.error as FetchBaseQueryError };
}
// Remove ?code= query param from
// url, we don't want it anymore.
window.history.replaceState({}, document.title, window.location.pathname);
// Store returned token in redux.
api.dispatch(oauthSetToken(tokenResult.data));
// We're now authed! So return
// standard verify_credentials query.
return fetchWithBQ({
url: `/api/v1/accounts/verify_credentials`
});
}
}),
authorizeFlow: builder.mutation({
async queryFn(formData, api, _extraOpts, fetchWithBQ) {
const state = api.getState() as RootState;
const oauthState = state.oauth;
let instanceUrl: string;
if (!formData.instance.startsWith("http")) {
formData.instance = `https://${formData.instance}`;
}
instanceUrl = new URL(formData.instance).origin;
if (oauthState?.instanceUrl == instanceUrl && oauthState.app) {
return { data: oauthState.app };
}
const appResult = await fetchWithBQ({
method: "POST",
baseUrl: instanceUrl,
url: "/api/v1/apps",
body: {
client_name: "GoToSocial Settings",
scopes: formData.scopes,
redirect_uris: SETTINGS_URL,
website: SETTINGS_URL
}
});
if (appResult.error) {
return { error: appResult.error as FetchBaseQueryError };
}
let app = appResult.data as any;
app.scopes = formData.scopes;
api.dispatch(oauthAuthorize({
instanceUrl: instanceUrl,
app: app,
loginState: "callback",
expectingRedirect: true
}));
let url = new URL(instanceUrl);
url.pathname = "/oauth/authorize";
url.searchParams.set("client_id", app.client_id);
url.searchParams.set("redirect_uri", SETTINGS_URL);
url.searchParams.set("response_type", "code");
url.searchParams.set("scope", app.scopes);
let redirectURL = url.toString();
window.location.assign(redirectURL);
return { data: null };
},
}),
logout: builder.mutation({
queryFn: (_arg, api) => {
api.dispatch(oauthRemove());
return { data: null };
},
invalidatesTags: ["Auth"]
})
})
});
export const {
useVerifyCredentialsQuery,
useAuthorizeFlowMutation,
useLogoutMutation,
} = extended;

View File

@ -17,29 +17,32 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
import { replaceCacheOnMutation } from "../lib";
import { gtsApi } from "../gts-api";
const { replaceCacheOnMutation } = require("./lib");
const base = require("./base");
const endpoints = (build) => ({
updateCredentials: build.mutation({
query: (formData) => ({
method: "PATCH",
url: `/api/v1/accounts/update_credentials`,
asForm: true,
body: formData,
discardEmpty: true
const extended = gtsApi.injectEndpoints({
endpoints: (builder) => ({
updateCredentials: builder.mutation({
query: (formData) => ({
method: "PATCH",
url: `/api/v1/accounts/update_credentials`,
asForm: true,
body: formData,
discardEmpty: true
}),
...replaceCacheOnMutation("verifyCredentials")
}),
...replaceCacheOnMutation("verifyCredentials")
}),
passwordChange: build.mutation({
query: (data) => ({
method: "POST",
url: `/api/v1/user/password_change`,
body: data
passwordChange: builder.mutation({
query: (data) => ({
method: "POST",
url: `/api/v1/user/password_change`,
body: data
})
})
})
});
module.exports = base.injectEndpoints({ endpoints });
export const {
useUpdateCredentialsMutation,
usePasswordChangeMutation,
} = extended;

View File

@ -1,44 +0,0 @@
/*
GoToSocial
Copyright (C) GoToSocial Authors admin@gotosocial.org
SPDX-License-Identifier: AGPL-3.0-or-later
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const { createSlice } = require("@reduxjs/toolkit");
module.exports = createSlice({
name: "oauth",
initialState: {
loginState: 'none',
expectingRedirect: false
},
reducers: {
authorize: (state, { payload }) => {
return payload; // overrides state
},
setToken: (state, { payload }) => {
state.token = `${payload.token_type} ${payload.access_token}`;
state.loginState = "login";
},
remove: (state, { _payload }) => {
delete state.token;
delete state.registration;
state.loginState = "logout";
}
}
});

View File

@ -0,0 +1,89 @@
/*
GoToSocial
Copyright (C) GoToSocial Authors admin@gotosocial.org
SPDX-License-Identifier: AGPL-3.0-or-later
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { PayloadAction, createSlice } from "@reduxjs/toolkit";
/**
* OAuthToken represents a response
* to an OAuth token request.
*/
export interface OAuthToken {
/**
* Most likely to be 'Bearer'
* but may be something else.
*/
token_type: string;
/**
* The actual token. Can be passed in to
* authenticate further requests using the
* Authorization header and the token type.
*/
access_token: string;
}
export interface OAuthApp {
client_id: string;
client_secret: string;
}
export interface OAuthState {
instanceUrl?: string;
loginState: "none" | "callback" | "login" | "logout";
expectingRedirect: boolean;
/**
* Token stored in easy-to-use format.
* Will look something like:
* "Authorization: Bearer BLAHBLAHBLAH"
*/
token?: string;
app?: OAuthApp;
}
const initialState: OAuthState = {
loginState: 'none',
expectingRedirect: false,
};
export const oauthSlice = createSlice({
name: "oauth",
initialState: initialState,
reducers: {
authorize: (_state, action: PayloadAction<OAuthState>) => {
// Overrides state with payload.
return action.payload;
},
setToken: (state, action: PayloadAction<OAuthToken>) => {
// Mark us as logged in by storing token.
state.token = `${action.payload.token_type} ${action.payload.access_token}`;
state.loginState = "login";
},
remove: (state) => {
// Mark us as logged out by clearing auth.
delete state.token;
delete state.app;
state.loginState = "logout";
}
}
});
export const {
authorize,
setToken,
remove,
} = oauthSlice.actions;

View File

@ -17,11 +17,9 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const { combineReducers } = require("redux");
const { configureStore } = require("@reduxjs/toolkit");
const {
import { combineReducers } from "redux";
import { configureStore } from "@reduxjs/toolkit";
import {
persistStore,
persistReducer,
FLUSH,
@ -30,14 +28,14 @@ const {
PERSIST,
PURGE,
REGISTER,
} = require("redux-persist");
} from "redux-persist";
const query = require("../lib/query/base");
const { Promise } = require("bluebird");
import { oauthSlice } from "./oauth";
import { gtsApi } from "../lib/query/gts-api";
const combinedReducers = combineReducers({
oauth: require("./oauth").reducer,
[query.reducerPath]: query.reducer
[gtsApi.reducerPath]: gtsApi.reducer,
oauth: oauthSlice.reducer,
});
const persistedReducer = persistReducer({
@ -45,27 +43,41 @@ const persistedReducer = persistReducer({
storage: require("redux-persist/lib/storage").default,
stateReconciler: require("redux-persist/lib/stateReconciler/autoMergeLevel1").default,
whitelist: ["oauth"],
migrate: (state) => {
return Promise.try(() => {
if (state?.oauth != undefined) {
state.oauth.expectingRedirect = false;
}
migrate: async (state) => {
if (state == undefined) {
return state;
});
}
// This is a cheeky workaround for
// redux-persist being a stickler.
let anyState = state as any;
if (anyState?.oauth != undefined) {
anyState.oauth.expectingRedirect = false;
}
return anyState;
}
}, combinedReducers);
const store = configureStore({
export const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) => {
return getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER]
ignoredActions: [
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER,
]
}
}).concat(query.middleware);
}).concat(gtsApi.middleware);
}
});
const persistor = persistStore(store);
export const persistor = persistStore(store);
module.exports = { store, persistor };
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const query = require("../lib/query");

View File

@ -17,8 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const React = require("react");
const query = require("../lib/query");

109
web/source/tsconfig.json Normal file
View File

@ -0,0 +1,109 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
/* Projects */
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
"jsx": "react" , /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
// "rootDir": "./", /* Specify the root folder within your source files. */
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
"allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
"noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
/* Type Checking */
"strict": false, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}

File diff suppressed because it is too large Load Diff