mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-02 18:39:05 +01:00
Fix All TypeScript Errors (#56)
* update newtab screen to make it match the figma mockup (still waiting on UI for name) * fix all typescript errors * update for new build * remove old import
This commit is contained in:
parent
9b5bc33125
commit
14715ec5b1
@ -59,6 +59,7 @@
|
||||
"@types/papaparse": "^5.3.9",
|
||||
"@types/react": "^18.0.12",
|
||||
"@types/uuid": "9.0.0",
|
||||
"@types/webpack-env": "^1.18.3",
|
||||
"babel-loader": "^9.1.3",
|
||||
"babel-plugin-jsx-control-statements": "^4.1.2",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
|
@ -33,7 +33,7 @@ PROMPT_DEV=1 PCLOUD_ENDPOINT="https://ot2e112zx5.execute-api.us-west-2.amazonaws
|
||||
```bash
|
||||
# @scripthaus command typecheck
|
||||
# @scripthaus cd :playbook
|
||||
node_modules/.bin/tsc --jsx preserve --noEmit --esModuleInterop --target ES5 --experimentalDecorators --downlevelIteration src/index.ts
|
||||
node_modules/.bin/tsc --jsx preserve --noEmit --esModuleInterop --target ES5 --experimentalDecorators --downlevelIteration src/index.ts src/types/custom.d.ts
|
||||
```
|
||||
|
||||
```bash
|
||||
@ -101,7 +101,7 @@ rm *.dmg
|
||||
DMG_VERSION=$(node -e 'console.log(require("./version.js"))')
|
||||
DMG_NAME="waveterm-macos-arm64-${DMG_VERSION}.dmg"
|
||||
rm *.dmg
|
||||
../../create-dmg/create-dmg/create-dmg \
|
||||
/Users/sawka/work/gopath/src/github.com/create-dmg/create-dmg/create-dmg \
|
||||
--volname "WaveTerm" \
|
||||
--window-pos 200 120 \
|
||||
--window-size 600 300 \
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { Component, ReactNode } from "react";
|
||||
import { RendererContext } from "../../../plugins/types/types";
|
||||
import { RendererContext } from "../../../types/types";
|
||||
import cn from "classnames";
|
||||
|
||||
interface ErrorBoundaryState {
|
||||
|
@ -9,7 +9,7 @@ import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import { GlobalModel, LineContainerModel } from "../../../model/model";
|
||||
import type { LineType, RemoteType, RemotePtrType, LineHeightChangeCallbackType } from "../../../types/types";
|
||||
import cn from "classnames";
|
||||
import { isBlank, getRemoteStr } from "../../../util/util";
|
||||
import { isBlank } from "../../../util/util";
|
||||
import { ReactComponent as FolderIcon } from "../../assets/icons/folder.svg";
|
||||
|
||||
import "./prompt.less";
|
||||
@ -33,6 +33,29 @@ type RendererComponentType = {
|
||||
new (props: RendererComponentProps): React.Component<RendererComponentProps, {}>;
|
||||
};
|
||||
|
||||
function makeFullRemoteRef(ownerName: string, remoteRef: string, name: string): string {
|
||||
if (isBlank(ownerName) && isBlank(name)) {
|
||||
return remoteRef;
|
||||
}
|
||||
if (!isBlank(ownerName) && isBlank(name)) {
|
||||
return ownerName + ":" + remoteRef;
|
||||
}
|
||||
if (isBlank(ownerName) && !isBlank(name)) {
|
||||
return remoteRef + ":" + name;
|
||||
}
|
||||
return ownerName + ":" + remoteRef + ":" + name;
|
||||
}
|
||||
|
||||
function getRemoteStr(rptr: RemotePtrType): string {
|
||||
if (rptr == null || isBlank(rptr.remoteid)) {
|
||||
return "(invalid remote)";
|
||||
}
|
||||
let username = isBlank(rptr.ownerid) ? null : GlobalModel.resolveUserIdToName(rptr.ownerid);
|
||||
let remoteRef = GlobalModel.resolveRemoteIdToRef(rptr.remoteid);
|
||||
let fullRef = makeFullRemoteRef(username, remoteRef, rptr.name);
|
||||
return fullRef;
|
||||
}
|
||||
|
||||
function getShortVEnv(venvDir: string): string {
|
||||
if (isBlank(venvDir)) {
|
||||
return "";
|
||||
@ -133,4 +156,4 @@ class Prompt extends React.Component<{ rptr: RemotePtrType; festate: Record<stri
|
||||
}
|
||||
}
|
||||
|
||||
export { Prompt };
|
||||
export { Prompt, getRemoteStr };
|
||||
|
@ -743,6 +743,7 @@ class Line extends React.Component<
|
||||
overrideCollapsed: OV<boolean>;
|
||||
renderMode: RenderModeType;
|
||||
noSelect?: boolean;
|
||||
topBorder: boolean;
|
||||
},
|
||||
{}
|
||||
> {
|
||||
|
@ -29,6 +29,6 @@ let m = MagicLayout;
|
||||
// add up all the line overhead + padding. subtract 2 so we don't see the border of neighboring line
|
||||
m.ScreenMaxContentHeightBuffer = m.LineHeaderHeight + m.LinePadding + m.WindowHeightOffset + m.LinesBottomPadding + m.LineMarginTop - 2;
|
||||
|
||||
window.MagicLayout = MagicLayout;
|
||||
(window as any).MagicLayout = MagicLayout;
|
||||
|
||||
export { MagicLayout };
|
||||
|
@ -7,7 +7,7 @@ import * as mobx from "mobx";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
import { GlobalModel } from "../../model/model";
|
||||
import { PluginModel } from "../../plugins/plugins";
|
||||
import { ImageDisplay, Markdown } from "../common/common";
|
||||
import { Markdown } from "../common/common";
|
||||
|
||||
import { ReactComponent as XmarkIcon } from "../assets/icons/line/xmark.svg";
|
||||
|
||||
@ -20,6 +20,11 @@ class PluginsView extends React.Component<{}, {}> {
|
||||
GlobalModel.pluginsModel.closeView();
|
||||
}
|
||||
|
||||
renderPluginIcon(plugin): any {
|
||||
let Comp = plugin.iconComp;
|
||||
return <Comp/>;
|
||||
}
|
||||
|
||||
render() {
|
||||
if (GlobalModel.activeMainView.get() !== "plugins") {
|
||||
return <></>;
|
||||
@ -37,7 +42,7 @@ class PluginsView extends React.Component<{}, {}> {
|
||||
onClick={() => pluginsModel.setSelectedPlugin(plugin)}
|
||||
>
|
||||
<div className="plugin-summary-header">
|
||||
<div className="plugin-summary-icon">{plugin.getIcon()}</div>
|
||||
<div className="plugin-summary-icon">{this.renderPluginIcon(plugin)}</div>
|
||||
<div className="plugin-summary-info">
|
||||
<div className="plugin-summary-title">{plugin.title}</div>
|
||||
<div className="plugin-summary-vendor">{plugin.vendor}</div>
|
||||
@ -54,7 +59,7 @@ class PluginsView extends React.Component<{}, {}> {
|
||||
return (
|
||||
<div className="plugins-details">
|
||||
<div className="plugin-summary-header">
|
||||
<div className="plugin-summary-icon">{plugin.getIcon()}</div>
|
||||
<div className="plugin-summary-icon">{this.renderPluginIcon(plugin)}</div>
|
||||
<div className="plugin-summary-info">
|
||||
<div className="plugin-summary-title">{plugin.title}</div>
|
||||
<div className="plugin-summary-vendor">{plugin.vendor}</div>
|
||||
|
@ -6,7 +6,7 @@ import * as mobxReact from "mobx-react";
|
||||
import * as mobx from "mobx";
|
||||
import { sprintf } from "sprintf-js";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
import { If } from "tsx-control-statements/components";
|
||||
import { If, For } from "tsx-control-statements/components";
|
||||
import cn from "classnames";
|
||||
import { debounce } from "throttle-debounce";
|
||||
import dayjs from "dayjs";
|
||||
@ -15,6 +15,7 @@ import type { LineType, RenderModeType, LineFactoryProps, CommandRtnType } from
|
||||
import * as T from "../../../types/types";
|
||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import { InlineSettingsTextEdit, RemoteStatusLight } from "../../common/common";
|
||||
import { getRemoteStr } from "../../common/prompt/prompt";
|
||||
import { GlobalModel, ScreenLines, Screen } from "../../../model/model";
|
||||
import { Line } from "../../line/linecomps";
|
||||
import { LinesView } from "../../line/linesview";
|
||||
@ -61,7 +62,7 @@ class NewTabSettings extends React.Component<{ screen: Screen }, {}> {
|
||||
if (screen.getTabColor() == color) {
|
||||
return;
|
||||
}
|
||||
let prtn = GlobalCommandRunner.screenSetSettings(this.props.screenId, { tabcolor: color }, false);
|
||||
let prtn = GlobalCommandRunner.screenSetSettings(screen.screenId, { tabcolor: color }, false);
|
||||
util.commandRtnHandler(prtn, this.errorMessage);
|
||||
}
|
||||
|
||||
@ -71,7 +72,7 @@ class NewTabSettings extends React.Component<{ screen: Screen }, {}> {
|
||||
if (util.isStrEq(val, screen.name.get())) {
|
||||
return;
|
||||
}
|
||||
let prtn = GlobalCommandRunner.screenSetSettings(this.props.screenId, { name: val }, false);
|
||||
let prtn = GlobalCommandRunner.screenSetSettings(screen.screenId, { name: val }, false);
|
||||
util.commandRtnHandler(prtn, this.errorMessage);
|
||||
}
|
||||
|
||||
@ -102,7 +103,7 @@ class NewTabSettings extends React.Component<{ screen: Screen }, {}> {
|
||||
renderConnDropdown(): any {
|
||||
let { screen } = this.props;
|
||||
let allRemotes = util.sortAndFilterRemotes(GlobalModel.remotes.slice());
|
||||
let remote: RemoteType = null;
|
||||
let remote: T.RemoteType = null;
|
||||
let curRemote = GlobalModel.getRemote(GlobalModel.getActiveScreen().getCurRemoteInstance().remoteid);
|
||||
// TODO no remote?
|
||||
return (
|
||||
@ -173,7 +174,7 @@ class NewTabSettings extends React.Component<{ screen: Screen }, {}> {
|
||||
<div className="newtab-container">
|
||||
<div className="newtab-section conn-section">
|
||||
<div className="text-s1">
|
||||
You're connected to [{util.getRemoteStr(rptr)}]. Do you want to change it?
|
||||
You're connected to [{getRemoteStr(rptr)}]. Do you want to change it?
|
||||
</div>
|
||||
<div>
|
||||
{this.renderConnDropdown()}
|
||||
|
@ -3676,7 +3676,7 @@ class Model {
|
||||
return remote.remotecanonicalname;
|
||||
}
|
||||
|
||||
readRemoteFile(screenId: string, lineId: string, path: string): Promise<File> {
|
||||
readRemoteFile(screenId: string, lineId: string, path: string): Promise<T.ExtFile> {
|
||||
let urlParams = {
|
||||
screenid: screenId,
|
||||
lineid: lineId,
|
||||
@ -3711,7 +3711,7 @@ class Model {
|
||||
let isWriteable = (fileInfo.perm & 0o222) > 0; // checks for unix permission "w" bits
|
||||
(file as any).readOnly = !isWriteable;
|
||||
(file as any).notFound = !!fileInfo.notfound;
|
||||
return file;
|
||||
return file as T.ExtFile;
|
||||
} else {
|
||||
let textError: string = blobOrText;
|
||||
if (textError == null || textError.length == 0) {
|
||||
|
@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import * as React from "react";
|
||||
import { RendererContext, RendererOpts, LineStateType, RendererModelContainerApi } from "../../types/types";
|
||||
import * as T from "../../types/types";
|
||||
import Editor from "@monaco-editor/react";
|
||||
import { Markdown } from "../../app/common/common";
|
||||
import { GlobalModel, GlobalCommandRunner } from "../../model/model";
|
||||
@ -21,20 +21,20 @@ declare var monaco: any;
|
||||
|
||||
class SourceCodeRenderer extends React.Component<
|
||||
{
|
||||
data: Blob;
|
||||
data: T.ExtBlob;
|
||||
cmdstr: string;
|
||||
cwd: string;
|
||||
readOnly: boolean;
|
||||
notFound: boolean;
|
||||
exitcode: number;
|
||||
context: RendererContext;
|
||||
opts: RendererOpts;
|
||||
context: T.RendererContext;
|
||||
opts: T.RendererOpts;
|
||||
savedHeight: number;
|
||||
scrollToBringIntoViewport: () => void;
|
||||
lineState: LineStateType;
|
||||
lineState: T.LineStateType;
|
||||
isSelected: boolean;
|
||||
shouldFocus: boolean;
|
||||
rendererApi: RendererModelContainerApi;
|
||||
rendererApi: T.RendererModelContainerApi;
|
||||
},
|
||||
{
|
||||
code: string;
|
||||
|
@ -17,6 +17,7 @@ import type {
|
||||
TermContextUnion,
|
||||
RendererContainerType,
|
||||
} from "../../types/types";
|
||||
import * as T from "../../types/types";
|
||||
import { debounce, throttle } from "throttle-debounce";
|
||||
import * as util from "../../util/util";
|
||||
import { GlobalModel } from "../../model/model";
|
||||
@ -37,7 +38,7 @@ class SimpleBlobRendererModel {
|
||||
lineState: LineStateType;
|
||||
ptyData: PtyDataType;
|
||||
ptyDataSource: (termContext: TermContextUnion) => Promise<PtyDataType>;
|
||||
dataBlob: Blob;
|
||||
dataBlob: T.ExtBlob;
|
||||
readOnly: boolean;
|
||||
notFound: boolean;
|
||||
|
||||
@ -146,7 +147,9 @@ class SimpleBlobRendererModel {
|
||||
}
|
||||
rtnp.then((ptydata) => {
|
||||
this.ptyData = ptydata;
|
||||
this.dataBlob = new Blob([this.ptyData.data]);
|
||||
let blob: T.ExtBlob = new Blob([this.ptyData.data]) as T.ExtBlob;
|
||||
blob.notFound = false;
|
||||
this.dataBlob = blob;
|
||||
mobx.action(() => {
|
||||
this.loading.set(false);
|
||||
this.loadError.set(null);
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
import React, { FC, useEffect, useState, useRef, useMemo } from "react";
|
||||
import { RendererContext, RendererOpts, LineStateType, RendererModelContainerApi } from "../../types/types";
|
||||
import * as T from "../../types/types";
|
||||
import { GlobalModel } from "../../model/model";
|
||||
import Papa from "papaparse";
|
||||
import {
|
||||
@ -27,14 +28,14 @@ type CSVRow = {
|
||||
};
|
||||
|
||||
interface Props {
|
||||
data: Blob;
|
||||
data: T.ExtBlob;
|
||||
readOnly: boolean;
|
||||
context: RendererContext;
|
||||
opts: RendererOpts;
|
||||
context: T.RendererContext;
|
||||
opts: T.RendererOpts;
|
||||
savedHeight: number;
|
||||
lineState: LineStateType;
|
||||
lineState: T.LineStateType;
|
||||
shouldFocus: boolean;
|
||||
rendererApi: RendererModelContainerApi;
|
||||
rendererApi: T.RendererModelContainerApi;
|
||||
scrollToBringIntoViewport: () => void;
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
import * as React from "react";
|
||||
import * as mobx from "mobx";
|
||||
import * as mobxReact from "mobx-react";
|
||||
import { RendererContext, RendererOpts } from "../../types/types";
|
||||
import * as T from "../../types/types";
|
||||
|
||||
import "./image.less";
|
||||
|
||||
@ -13,7 +13,7 @@ type CV<V> = mobx.IComputedValue<V>;
|
||||
|
||||
@mobxReact.observer
|
||||
class SimpleImageRenderer extends React.Component<
|
||||
{ data: Blob; context: RendererContext; opts: RendererOpts; savedHeight: number },
|
||||
{ data: T.ExtBlob; context: T.RendererContext; opts: T.RendererOpts; savedHeight: number },
|
||||
{}
|
||||
> {
|
||||
objUrl: string = null;
|
||||
|
@ -4,7 +4,7 @@
|
||||
import * as React from "react";
|
||||
import * as mobx from "mobx";
|
||||
import * as mobxReact from "mobx-react";
|
||||
import { RendererContext, RendererOpts } from "../../types/types";
|
||||
import * as T from "../../types/types";
|
||||
import { sprintf } from "sprintf-js";
|
||||
import { Markdown } from "../../app/common/common";
|
||||
|
||||
@ -16,7 +16,7 @@ const MaxMarkdownSize = 200000;
|
||||
|
||||
@mobxReact.observer
|
||||
class SimpleMarkdownRenderer extends React.Component<
|
||||
{ data: Blob; context: RendererContext; opts: RendererOpts; savedHeight: number },
|
||||
{ data: T.ExtBlob; context: T.RendererContext; opts: T.RendererOpts; savedHeight: number },
|
||||
{}
|
||||
> {
|
||||
markdownText: OV<string> = mobx.observable.box(null, { name: "markdownText" });
|
||||
|
@ -17,7 +17,7 @@ type OV<V> = mobx.IObservableValue<V>;
|
||||
|
||||
@mobxReact.observer
|
||||
class SimpleMustacheRenderer extends React.Component<
|
||||
{ data: Blob; context: T.RendererContext; opts: T.RendererOpts; savedHeight: number; lineState: T.LineStateType },
|
||||
{ data: T.ExtBlob; context: T.RendererContext; opts: T.RendererOpts; savedHeight: number; lineState: T.LineStateType },
|
||||
{}
|
||||
> {
|
||||
templateLoading: OV<boolean> = mobx.observable.box(true, { name: "templateLoading" });
|
||||
|
@ -152,7 +152,7 @@ class PluginModelClass {
|
||||
const handleImportError = (error, resourceType) =>
|
||||
console.error(`Failed to load ${resourceType} for plugin ${plugin.name}`);
|
||||
const iconPromise = import(`../plugins/${plugin.name}/icon.svg`)
|
||||
.then((icon) => (plugin.getIcon = icon.ReactComponent))
|
||||
.then((icon) => (plugin.iconComp = icon.ReactComponent))
|
||||
.catch((error) => handleImportError(error, "icon"));
|
||||
const readmePromise = import(`../plugins/${plugin.name}/readme.md`)
|
||||
.then((content) => (plugin.readme = content.default))
|
||||
|
6
src/types/custom.d.ts
vendored
Normal file
6
src/types/custom.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
declare module '*.svg' {
|
||||
import * as React from 'react';
|
||||
export const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement> & { title?: string }>;
|
||||
const src: string;
|
||||
export default src;
|
||||
}
|
@ -381,6 +381,12 @@ type RendererPluginType = {
|
||||
modelCtor?: () => RendererModel;
|
||||
simpleComponent?: SimpleBlobRendererComponent;
|
||||
fullComponent?: FullRendererComponent;
|
||||
readme?: string;
|
||||
screenshots?: any[];
|
||||
vendor?: string;
|
||||
summary?: string;
|
||||
title?: string;
|
||||
iconComp?: React.Component<{}, {}>;
|
||||
};
|
||||
|
||||
type RendererModelContainerApi = {
|
||||
@ -412,7 +418,7 @@ type RendererModel = {
|
||||
};
|
||||
|
||||
type SimpleBlobRendererComponent = React.ComponentType<{
|
||||
data: Blob;
|
||||
data: ExtBlob;
|
||||
readOnly?: boolean;
|
||||
notFound?: boolean;
|
||||
isSelected?: boolean;
|
||||
@ -624,6 +630,14 @@ type FileInfoType = {
|
||||
notfound: boolean;
|
||||
};
|
||||
|
||||
type ExtBlob = Blob & {
|
||||
notFound: boolean;
|
||||
};
|
||||
|
||||
type ExtFile = File & {
|
||||
notFound: boolean;
|
||||
};
|
||||
|
||||
export type {
|
||||
SessionDataType,
|
||||
LineStateType,
|
||||
@ -693,4 +707,6 @@ export type {
|
||||
CommandRtnType,
|
||||
OpenAIPacketType,
|
||||
FileInfoType,
|
||||
ExtBlob,
|
||||
ExtFile,
|
||||
};
|
||||
|
@ -5,7 +5,9 @@ import * as mobx from "mobx";
|
||||
import { sprintf } from "sprintf-js";
|
||||
import dayjs from "dayjs";
|
||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import type { RemoteType } from "../types/types";
|
||||
import type { RemoteType, CommandRtnType } from "../types/types";
|
||||
|
||||
type OV<V> = mobx.IObservableValue<V>;
|
||||
|
||||
dayjs.extend(localizedFormat);
|
||||
|
||||
@ -401,29 +403,6 @@ function generateBackgroundWithGradient(colorName = "white", decay = 3) {
|
||||
return `linear-gradient(180deg, rgba(${r}, ${g}, ${b}, ${opacities[0]}) ${percentages[0]}%, rgba(${r}, ${g}, ${b}, ${opacities[1]}) ${percentages[1]}%, rgba(${r}, ${g}, ${b}, 0) ${percentages[2]}%)`;
|
||||
}
|
||||
|
||||
function makeFullRemoteRef(ownerName: string, remoteRef: string, name: string): string {
|
||||
if (isBlank(ownerName) && isBlank(name)) {
|
||||
return remoteRef;
|
||||
}
|
||||
if (!isBlank(ownerName) && isBlank(name)) {
|
||||
return ownerName + ":" + remoteRef;
|
||||
}
|
||||
if (isBlank(ownerName) && !isBlank(name)) {
|
||||
return remoteRef + ":" + name;
|
||||
}
|
||||
return ownerName + ":" + remoteRef + ":" + name;
|
||||
}
|
||||
|
||||
function getRemoteStr(rptr: RemotePtrType): string {
|
||||
if (rptr == null || isBlank(rptr.remoteid)) {
|
||||
return "(invalid remote)";
|
||||
}
|
||||
let username = isBlank(rptr.ownerid) ? null : GlobalModel.resolveUserIdToName(rptr.ownerid);
|
||||
let remoteRef = GlobalModel.resolveRemoteIdToRef(rptr.remoteid);
|
||||
let fullRef = makeFullRemoteRef(username, remoteRef, rptr.name);
|
||||
return fullRef;
|
||||
}
|
||||
|
||||
function commandRtnHandler(prtn: Promise<CommandRtnType>, errorMessage: OV<string>) {
|
||||
prtn.then((crtn) => {
|
||||
if (crtn.success) {
|
||||
@ -458,6 +437,5 @@ export {
|
||||
openLink,
|
||||
generateBackgroundWithGradient,
|
||||
getColorRGB,
|
||||
getRemoteStr,
|
||||
commandRtnHandler,
|
||||
};
|
||||
|
@ -1966,6 +1966,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.0.tgz#53ef263e5239728b56096b0a869595135b7952d2"
|
||||
integrity sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==
|
||||
|
||||
"@types/webpack-env@^1.18.3":
|
||||
version "1.18.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.18.3.tgz#e81f769199a5609c751f34fcc6f6095ceac7831f"
|
||||
integrity sha512-v4CH6FLBCftYGFAswDhzFLjKgucXsOkIf5Mzl8ZZhEtC6oye9whFInNPKszNB9AvX7JEZMtpXxWctih6addP+Q==
|
||||
|
||||
"@types/ws@^8.5.5":
|
||||
version "8.5.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.6.tgz#e9ad51f0ab79b9110c50916c9fcbddc36d373065"
|
||||
|
Loading…
Reference in New Issue
Block a user