Skip to content

Commit

Permalink
Update NPM packaging, linting, and a bunch of types (#275)
Browse files Browse the repository at this point in the history
Preparation for
webrecorder/archiveweb.page#198 /
webrecorder/archiveweb.page#199.

## Changes

- Organizes published files more cleanly, using `dist/types` folder as
the target for type declarations and sourcemaps
- Configures type field in `package.json`
- Updates ESLint & its config
  - Sets up type-informed linting rules mirroring browsertrix
- Adds a bunch of other useful eslint and eslint-typescript rules, and
applies auto-fixes to the codebase
- Cleans up a bunch of types throughout the codebase, particularly parts
of the code used by ArchiveWebPage
- Changes `ItemIndex#_deleting` from `private` to `protected` so that a
part of AWP that extends it can do so properly
- Makes a bunch of previously-implied [non-null
assertions](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#non-null-assertion-operator-postfix-)
explicit
- Updates `URLResource` and `ItemType` types (and renames `Item` →
`ItemType` to disambiguate from the `Item` class)
- Removes `node-sass` and replaces it with `sass-embedded` for much
quicker installs and compilation
  • Loading branch information
emma-sg committed Feb 7, 2024
1 parent a404711 commit a63390f
Show file tree
Hide file tree
Showing 32 changed files with 897 additions and 1,549 deletions.
104 changes: 91 additions & 13 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,110 @@
/* eslint-env node */
/** @type { import("eslint").Linter.Config } */
/** @type {import('eslint').Linter.Config} */
module.exports = {
parser: "@typescript-eslint/parser",
env: {
browser: true,
es6: true,
commonjs: true,
es2017: true,
},
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:wc/recommended",
"plugin:lit/recommended",
"prettier",
"plugin:@typescript-eslint/recommended",
],
plugins: ["@typescript-eslint", "lit"],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: 2018,
sourceType: "module",
project: ["./tsconfig.eslint.json"],
tsconfigRootDir: __dirname,
},
root: true,
rules: {
/* start stylistic rules */
"@typescript-eslint/adjacent-overload-signatures": "error",
"@typescript-eslint/array-type": "error",
"@typescript-eslint/consistent-type-imports": [
"error",
{
fixStyle: "inline-type-imports",
},
],
"@typescript-eslint/prefer-readonly": "warn",
"@typescript-eslint/class-literal-property-style": ["warn", "getters"],
"@typescript-eslint/consistent-generic-constructors": "error",
"@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/no-confusing-non-null-assertion": "warn",
"@typescript-eslint/no-inferrable-types": "warn",
"@typescript-eslint/non-nullable-type-assertion-style": "warn",
"@typescript-eslint/prefer-for-of": "warn",
// "@typescript-eslint/prefer-nullish-coalescing": "warn",
"@typescript-eslint/prefer-optional-chain": "warn",
"@typescript-eslint/prefer-string-starts-ends-with": "error",
/* end stylistic rules */

/* start recommended rules */
"no-restricted-globals": [2, "event", "error"],
"linebreak-style": ["error", "unix"],
"@typescript-eslint/no-base-to-string": "warn",
"@typescript-eslint/no-duplicate-enum-values": "error",
"@typescript-eslint/no-duplicate-type-constituents": "warn",
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-extra-non-null-assertion": "error",
// "@typescript-eslint/no-floating-promises": "warn",
"@typescript-eslint/no-for-in-array": "warn",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": [
"warn",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
destructuredArrayIgnorePattern: "^_",
},
],
"no-implied-eval": "off",
"@typescript-eslint/no-implied-eval": "error",
"no-loss-of-precision": "off",
"@typescript-eslint/no-loss-of-precision": "warn",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-misused-promises": [
"error",
{ checksVoidReturn: { arguments: false } },
],
"@typescript-eslint/no-non-null-asserted-nullish-coalescing": "error",
"@typescript-eslint/no-non-null-asserted-optional-chain": "warn",
"@typescript-eslint/no-redundant-type-constituents": "warn",
"@typescript-eslint/no-this-alias": "warn",
"@typescript-eslint/no-unnecessary-type-assertion": "warn",
"@typescript-eslint/no-unnecessary-type-constraint": "warn",
// "@typescript-eslint/no-unsafe-argument": "warn",
// "@typescript-eslint/no-unsafe-assignment": "warn",
// "@typescript-eslint/no-unsafe-call": "warn",
"@typescript-eslint/no-unsafe-declaration-merging": "warn",
"@typescript-eslint/no-unsafe-enum-comparison": "warn",
// "@typescript-eslint/no-unsafe-member-access": "warn",
// "@typescript-eslint/no-unsafe-return": "warn",
"@typescript-eslint/prefer-as-const": "warn",
"require-await": "off",
"@typescript-eslint/require-await": "warn",
"@typescript-eslint/restrict-template-expressions": "warn",
"@typescript-eslint/unbound-method": "off",
},
reportUnusedDisableDirectives: true,
ignorePatterns: [
"ruffle/**/*",
"build/**/*",
"/sw.js",
"/ui.js",
"dist/**/*",
"__generated__",
"__mocks__",
"dist",
"ruffle",
"ui.js",
"sw.js",
],
overrides: [
{
extends: ["plugin:@typescript-eslint/disable-type-checked"],
files: ["webpack.*.js"],
rules: {
"@typescript-eslint/no-var-requires": "off",
},
},
],
reportUnusedDisableDirectives: true,
};
3 changes: 2 additions & 1 deletion build/notarize.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/*eslint-env node */
const { notarize } = require('electron-notarize');

exports.default = async function notarizing(context) {
const { electronPlatformName, appOutDir } = context;
const { electronPlatformName, appOutDir } = context;
if (electronPlatformName !== 'darwin') {
return;
}
Expand Down
1 change: 0 additions & 1 deletion index.js

This file was deleted.

20 changes: 11 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
"homepage": "https://replayweb.page/",
"author": "Webrecorder Software",
"license": "AGPL-3.0-or-later",
"main": "ui.js",
"types": "dist/types/index.d.ts",
"dependencies": {
"@fortawesome/fontawesome-free": "^5.15.4",
"@shoelace-style/shoelace": "^2.8.0",
Expand All @@ -29,26 +31,27 @@
"stream-browserify": "^3.0.0"
},
"devDependencies": {
"@types/flexsearch": "^0.7.3",
"@typescript-eslint/eslint-plugin": "^6.9.1",
"@typescript-eslint/parser": "^6.9.1",
"@playwright/test": "^1.38.1",
"@types/flexsearch": "^0.7.3",
"@typescript-eslint/eslint-plugin": "^6.12.0",
"@typescript-eslint/parser": "^6.12.0",
"copy-webpack-plugin": "^9.0.1",
"css-loader": "^6.2.0",
"electron": "^25.1.1",
"electron-builder": "^23.0.3",
"electron-notarize": "^1.1.1",
"eslint": "^8.52.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-lit": "^1.9.1",
"eslint": "^8.54.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-lit": "^1.10.1",
"eslint-plugin-wc": "^1.3.2",
"http-server": "^13.0.2",
"husky": "^8.0.0",
"lint-staged": "^14.0.0",
"mini-css-extract-plugin": "^2.3.0",
"node-sass": "^9.0.0",
"playwright": "^1.38.1",
"prettier": "^3.0.1",
"raw-loader": "^4.0.2",
"sass-embedded": "^1.70.0",
"sass-loader": "^13.3.2",
"style-loader": "^3.2.1",
"svg-inline-loader": "^0.8.2",
Expand All @@ -62,11 +65,11 @@
},
"files": [
"/assets",
"/dist",
"/src",
"/ruffle",
"sw.js",
"ui.js",
"index.js",
"index.html"
],
"scripts": {
Expand Down Expand Up @@ -102,7 +105,6 @@
"dist/*.js",
"dist/prebuilds/${platform}-${arch}/*",
"dist/build/*",
"index.js",
"ui.js",
"sw.js",
"*.html",
Expand Down
3 changes: 1 addition & 2 deletions scripts/build-if-not-git-repo.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-env node */

// Runs a webpack build when not installed in a git repository (i.e. when installed from GitHub in node_modules)
Expand Down Expand Up @@ -26,7 +25,7 @@ const git = (args) => cp.spawnSync("git", args, { stdio: "inherit" });
// Ensure that we're inside a Git repository
// If git command is not found, status is null and we should return
// That's why status value needs to be checked explicitly
if (git(["rev-parse"]).status !== 0) {
if (git(["rev-parse"]).status !== 0 || process.argv.includes("--force")) {
l(`git command not found, running build`);
const compiler = webpack(config.map((c) => c()));

Expand Down
25 changes: 11 additions & 14 deletions src/appmain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
LitElement,
html,
css,
type CSSResultGroup,
type TemplateResult,
type PropertyValues,
} from "lit";
Expand All @@ -22,7 +23,7 @@ import { SWManager } from "./swmanager";
import "./item";
import "./item-index";
import "./chooser";
import { LoadInfo } from "./item";
import { type LoadInfo } from "./item";

// ===========================================================================
@customElement("replay-app-main")
Expand Down Expand Up @@ -69,10 +70,10 @@ export class ReplayWebApp extends LitElement {
@property({ type: Boolean })
skipRuffle = false;

@property({ type: Object })
swErrorMsg: TemplateResult<1> | "" | null = null;
@property({ type: String })
swErrorMsg: TemplateResult<1> | string | null = null;

private swName?: string;
protected swName?: string;
private swmanager: SWManager | null;
private useRuffle = false;

Expand Down Expand Up @@ -112,7 +113,7 @@ export class ReplayWebApp extends LitElement {
});
}

private maybeStartFileDrop = (dragEvent: DragEvent) => {
private readonly maybeStartFileDrop = (dragEvent: DragEvent) => {
if (this.sourceUrl) {
// A source is already loaded. Don't allow dropping a file.
return;
Expand All @@ -133,7 +134,7 @@ export class ReplayWebApp extends LitElement {
return wrapCss(ReplayWebApp.appStyles);
}

static get appStyles() {
static get appStyles(): CSSResultGroup {
return css`
#wrlogo {
max-height: 1rem;
Expand Down Expand Up @@ -237,7 +238,7 @@ export class ReplayWebApp extends LitElement {
}

get mainLogo() {
return rwpLogo;
return rwpLogo as string;
}

renderNavBrand() {
Expand Down Expand Up @@ -499,7 +500,7 @@ export class ReplayWebApp extends LitElement {
// This is a workaround, since this app's routing doesn't permit normal
// following of in-page anchors.
event.preventDefault();
(this.renderRoot.querySelector("#skip-main-target") as HTMLElement).focus();
this.renderRoot.querySelector<HTMLElement>("#skip-main-target")?.focus();
}

onNavMenu(event) {
Expand All @@ -516,9 +517,7 @@ export class ReplayWebApp extends LitElement {
(event) => {
event.preventDefault();
this.navMenuShown = false;
(
this.renderRoot.querySelector("#menu-button") as HTMLElement
).focus();
this.renderRoot.querySelector<HTMLElement>("#menu-button")?.focus();
},
{ once: true },
);
Expand All @@ -528,9 +527,7 @@ export class ReplayWebApp extends LitElement {
if (event.key == "Escape") {
event.preventDefault();
this.navMenuShown = false;
(
this.renderRoot.querySelector("#menu-button") as HTMLElement
).focus();
this.renderRoot.querySelector<HTMLElement>("#menu-button")?.focus();
}
},
{ once: true },
Expand Down
32 changes: 10 additions & 22 deletions src/electron-preload.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*eslint-env node */

import { CollectionLoader } from "@webrecorder/wabac/src/loaders";
import { type IpcRendererEvent } from "electron";

// eslint-disable-next-line @typescript-eslint/no-var-requires
const { ipcRenderer, contextBridge } = require("electron");

contextBridge.exposeInMainWorld("electron", { IS_APP: true });
Expand All @@ -11,12 +11,7 @@ const dbs = {};

const loader = new CollectionLoader();

/**
*
* @param {string} name
* @returns
*/
async function getColl(name) {
async function getColl(name: string) {
if (!dbs[name]) {
dbs[name] = await loader.loadColl(name);
await dbs[name].initing;
Expand All @@ -25,25 +20,18 @@ async function getColl(name) {
return dbs[name];
}

/**
* @param {string} name
* @returns
*/
async function getDB(name) {
async function getDB(name: string) {
const coll = await getColl(name);
return coll.store;
}

/**
*
* @param {import("electron").IpcRendererEvent} event
* @param {*} request
* @param {*} coll
* @param {*} ts
* @param {*} channel
* @returns
*/
async function getResponse(event, request, coll, ts, channel) {
async function getResponse(
event: IpcRendererEvent,
request: Request,
coll: string,
ts: string,
channel: string,
): Promise<void> {
const db = await getDB(coll);

const req = { request, url: request.url, timestamp: ts };
Expand Down
12 changes: 9 additions & 3 deletions src/electron-replay-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,14 @@ class ElectronReplayApp {
return rv;
}

async doIntercept(request, callback) {
async doIntercept(
request,
callback: (response: {
statusCode: number;
headers: Record<string, string>;
data: fs.ReadStream;
}) => void,
) {
console.log(`${request.method} ${request.url} from ${request.referrer}`);

// if local server
Expand Down Expand Up @@ -303,7 +310,7 @@ class ElectronReplayApp {
}

// possible 'live leak' attempt, return archived version, if any
if (request.referrer && request.referrer.startsWith(REPLAY_PREFIX)) {
if (request.referrer?.startsWith(REPLAY_PREFIX)) {
return await this.resolveArchiveResponse(request, callback);
}

Expand Down Expand Up @@ -483,7 +490,6 @@ class ElectronReplayApp {
}

getOpenUrl(argv) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
argv = require("minimist")(argv.slice(process.defaultApp ? 2 : 1));

const filename =
Expand Down
Loading

0 comments on commit a63390f

Please sign in to comment.