aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2024-02-16 19:37:01 -0500
committerGitHub <noreply@github.com>2024-02-17 00:37:01 +0000
commit4e77741d22778bd09b772fc53f1cbd64107e3d24 (patch)
treee8010d42ccba5341afd98177d3c1d69d856cbcbd
parent1e69210b53151f31140bb1fbdc9f3d71fa181630 (diff)
Even more eslint rules (#696)
* capitalized-comments * Turn rules on * Add miscellaneous rules * More rules
-rw-r--r--.eslintrc.json36
-rw-r--r--dev/generate-css-json.js1
-rw-r--r--dev/util.js8
-rw-r--r--ext/js/background/backend.js6
-rw-r--r--ext/js/background/offscreen-proxy.js2
-rw-r--r--ext/js/background/profile-conditions-util.js2
-rw-r--r--ext/js/data/permissions-util.js72
-rw-r--r--ext/js/dictionary/dictionary-data-util.js2
-rw-r--r--ext/js/dom/dom-text-scanner.js6
-rw-r--r--ext/js/language/ja/japanese.js6
-rw-r--r--ext/js/language/translator.js2
-rw-r--r--ext/js/pages/permissions-main.js4
-rw-r--r--test/fixtures/dom-test.js1
-rw-r--r--test/language-transformer.test.js3
-rw-r--r--test/options-util.test.js14
-rw-r--r--test/playwright/integration.spec.js4
-rw-r--r--test/playwright/playwright-util.js2
-rw-r--r--test/playwright/visual.spec.js12
-rw-r--r--test/profile-conditions-util.test.js4
-rw-r--r--test/utilities/translator.js1
-rw-r--r--types/ext/application.d.ts3
21 files changed, 116 insertions, 75 deletions
diff --git a/.eslintrc.json b/.eslintrc.json
index 30d495d2..361e5f24 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -42,18 +42,42 @@
"/dev/lib/handlebars/"
],
"rules": {
+ "accessor-pairs": "error",
+ "capitalized-comments": [
+ "error",
+ "always",
+ {
+ "ignorePattern": "case|[a-z]+[A-Z0-9]|[a-z]+\\.\\w",
+ "ignoreInlineComments": true,
+ "ignoreConsecutiveComments": true
+ }
+ ],
"curly": ["error", "all"],
+ "default-case-last": "error",
"dot-notation": "error",
"eqeqeq": "error",
"func-names": ["error", "always"],
"guard-for-in": "error",
+ "grouped-accessor-pairs": "error",
+ "new-cap": "error",
+ "no-alert": "error",
"no-case-declarations": "error",
+ "no-caller": "error",
"no-const-assign": "error",
- "no-constant-condition": "off",
+ "no-constant-condition": ["error", {"checkLoops": false}],
+ "no-constructor-return": "error",
+ "no-duplicate-imports": "error",
+ "no-eval": "error",
+ "no-extend-native": "error",
"no-global-assign": "error",
"no-implicit-globals": "error",
+ "no-implied-eval": "error",
"no-new": "error",
+ "no-new-native-nonconstructor": "error",
+ "no-octal": "off",
+ "no-octal-escape": "off",
"no-param-reassign": "off",
+ "no-promise-executor-return": "error",
"no-prototype-builtins": "error",
"no-restricted-syntax": [
"error",
@@ -66,7 +90,11 @@
"selector": "MemberExpression[property.name=json]"
}
],
- "no-shadow": ["off", {"builtinGlobals": false}],
+ "no-self-compare": "error",
+ "no-sequences": "error",
+ "no-shadow": ["error", {"builtinGlobals": false}],
+ "no-shadow-restricted-names": "error",
+ "no-template-curly-in-string": "error",
"no-undef": "error",
"no-undefined": "error",
"no-underscore-dangle": ["error", {"allowAfterThis": true, "allowAfterSuper": false, "allowAfterThisConstructor": false}],
@@ -75,8 +103,12 @@
"no-unused-vars": ["error", {"vars": "local", "args": "after-used", "argsIgnorePattern": "^_", "caughtErrors": "none"}],
"no-unused-expressions": "error",
"no-var": "error",
+ "no-with": "error",
"prefer-const": ["error", {"destructuring": "all"}],
+ "radix": "error",
"require-atomic-updates": "off",
+ "sort-imports": "off",
+ "yoda": ["error", "never"],
"@stylistic/array-bracket-newline": ["error", "consistent"],
"@stylistic/array-bracket-spacing": ["error", "never"],
diff --git a/dev/generate-css-json.js b/dev/generate-css-json.js
index a837c9e2..adb75495 100644
--- a/dev/generate-css-json.js
+++ b/dev/generate-css-json.js
@@ -91,6 +91,7 @@ function removeProperty(styles, property, removedProperties) {
* @returns {string}
*/
export function formatRulesJson(rules) {
+ // This is similar to the following code, but formatted a but more succinctly:
// return JSON.stringify(rules, null, 4);
const indent1 = ' ';
const indent2 = indent1.repeat(2);
diff --git a/dev/util.js b/dev/util.js
index eee16964..817b0d84 100644
--- a/dev/util.js
+++ b/dev/util.js
@@ -57,7 +57,7 @@ export function getAllFiles(baseDirectory, predicate = null) {
export function createDictionaryArchive(dictionaryDirectory, dictionaryName) {
const fileNames = fs.readdirSync(dictionaryDirectory);
- // const zipFileWriter = new BlobWriter();
+ // Const zipFileWriter = new BlobWriter();
// const zipWriter = new ZipWriter(zipFileWriter);
const archive = new JSZip();
@@ -70,7 +70,7 @@ export function createDictionaryArchive(dictionaryDirectory, dictionaryName) {
}
archive.file(fileName, JSON.stringify(json, null, 0));
- // await zipWriter.add(fileName, new TextReader(JSON.stringify(json, null, 0)));
+ // Await zipWriter.add(fileName, new TextReader(JSON.stringify(json, null, 0)));
} else {
const content = fs.readFileSync(path.join(dictionaryDirectory, fileName), {encoding: null});
archive.file(fileName, content);
@@ -83,14 +83,14 @@ export function createDictionaryArchive(dictionaryDirectory, dictionaryName) {
// console.log('??');
}
}
- // await zipWriter.close();
+ // Await zipWriter.close();
// Retrieves the Blob object containing the zip content into `zipFileBlob`. It
// is also returned by zipWriter.close() for more convenience.
// const zipFileBlob = await zipFileWriter.getData();
return archive;
- // return zipFileBlob;
+ // Return zipFileBlob;
}
/**
diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js
index 8ab56232..e246f0bb 100644
--- a/ext/js/background/backend.js
+++ b/ext/js/background/backend.js
@@ -437,7 +437,7 @@ export class Backend {
/** @type {import('api').ApiHandler<'requestBackendReadySignal'>} */
_onApiRequestBackendReadySignal(_params, sender) {
- // tab ID isn't set in background (e.g. browser_action)
+ // Tab ID isn't set in background (e.g. browser_action)
/** @type {import('application').ApiMessage<'applicationBackendReady'>} */
const data = {action: 'applicationBackendReady'};
if (typeof sender.tab === 'undefined') {
@@ -1547,7 +1547,7 @@ export class Backend {
return (
isObject(chrome.action) &&
typeof chrome.action.getTitle === 'function' ?
- new Promise((resolve) => chrome.action.getTitle({}, resolve)) :
+ new Promise((resolve) => { chrome.action.getTitle({}, resolve); }) :
Promise.resolve('')
);
}
@@ -2601,7 +2601,7 @@ export class Backend {
const match = /^\d+/.exec(version);
if (match === null) { return; }
- const versionNumber = Number.parseInt(match[0]);
+ const versionNumber = Number.parseInt(match[0], 10);
if (!(Number.isFinite(versionNumber) && versionNumber >= 77)) { return; }
await navigator.storage.persist();
diff --git a/ext/js/background/offscreen-proxy.js b/ext/js/background/offscreen-proxy.js
index 085048c1..5a79f41a 100644
--- a/ext/js/background/offscreen-proxy.js
+++ b/ext/js/background/offscreen-proxy.js
@@ -85,7 +85,7 @@ export class OffscreenProxy {
*/
async _hasOffscreenDocument() {
const offscreenUrl = chrome.runtime.getURL('offscreen.html');
- if (!chrome.runtime.getContexts) { // chrome version below 116
+ if (!chrome.runtime.getContexts) { // Chrome version below 116
// Clients: https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/clients
// @ts-expect-error - Types not set up for service workers yet
const matchedClients = await clients.matchAll();
diff --git a/ext/js/background/profile-conditions-util.js b/ext/js/background/profile-conditions-util.js
index e2d58725..4e4e38d7 100644
--- a/ext/js/background/profile-conditions-util.js
+++ b/ext/js/background/profile-conditions-util.js
@@ -229,7 +229,7 @@ function createSchemaPopupLevelGreaterThanOrEqual(value) {
};
}
-// url schema creation functions
+// URL schema creation functions
/**
* @param {string} value
diff --git a/ext/js/data/permissions-util.js b/ext/js/data/permissions-util.js
index 097fe34d..1ccc630f 100644
--- a/ext/js/data/permissions-util.js
+++ b/ext/js/data/permissions-util.js
@@ -40,14 +40,16 @@ function ankiFieldMarkerMayUseClipboard(marker) {
* @returns {Promise<boolean>}
*/
export function hasPermissions(permissions) {
- return new Promise((resolve, reject) => chrome.permissions.contains(permissions, (result) => {
- const e = chrome.runtime.lastError;
- if (e) {
- reject(new Error(e.message));
- } else {
- resolve(result);
- }
- }));
+ return new Promise((resolve, reject) => {
+ chrome.permissions.contains(permissions, (result) => {
+ const e = chrome.runtime.lastError;
+ if (e) {
+ reject(new Error(e.message));
+ } else {
+ resolve(result);
+ }
+ });
+ });
}
/**
@@ -58,22 +60,26 @@ export function hasPermissions(permissions) {
export function setPermissionsGranted(permissions, shouldHave) {
return (
shouldHave ?
- new Promise((resolve, reject) => chrome.permissions.request(permissions, (result) => {
- const e = chrome.runtime.lastError;
- if (e) {
- reject(new Error(e.message));
- } else {
- resolve(result);
- }
- })) :
- new Promise((resolve, reject) => chrome.permissions.remove(permissions, (result) => {
- const e = chrome.runtime.lastError;
- if (e) {
- reject(new Error(e.message));
- } else {
- resolve(!result);
- }
- }))
+ new Promise((resolve, reject) => {
+ chrome.permissions.request(permissions, (result) => {
+ const e = chrome.runtime.lastError;
+ if (e) {
+ reject(new Error(e.message));
+ } else {
+ resolve(result);
+ }
+ });
+ }) :
+ new Promise((resolve, reject) => {
+ chrome.permissions.remove(permissions, (result) => {
+ const e = chrome.runtime.lastError;
+ if (e) {
+ reject(new Error(e.message));
+ } else {
+ resolve(!result);
+ }
+ });
+ })
);
}
@@ -81,14 +87,16 @@ export function setPermissionsGranted(permissions, shouldHave) {
* @returns {Promise<chrome.permissions.Permissions>}
*/
export function getAllPermissions() {
- return new Promise((resolve, reject) => chrome.permissions.getAll((result) => {
- const e = chrome.runtime.lastError;
- if (e) {
- reject(new Error(e.message));
- } else {
- resolve(result);
- }
- }));
+ return new Promise((resolve, reject) => {
+ chrome.permissions.getAll((result) => {
+ const e = chrome.runtime.lastError;
+ if (e) {
+ reject(new Error(e.message));
+ } else {
+ resolve(result);
+ }
+ });
+ });
}
/**
diff --git a/ext/js/dictionary/dictionary-data-util.js b/ext/js/dictionary/dictionary-data-util.js
index a2a106cc..a90668f4 100644
--- a/ext/js/dictionary/dictionary-data-util.js
+++ b/ext/js/dictionary/dictionary-data-util.js
@@ -286,7 +286,7 @@ export function isNonNounVerbOrAdjective(wordClasses) {
case 'vs':
isVerbOrAdjective = true;
isSuruVerb = true;
- // falls through
+ // Falls through
case 'n':
isNoun = true;
break;
diff --git a/ext/js/dom/dom-text-scanner.js b/ext/js/dom/dom-text-scanner.js
index 5b3ea564..e263d9f3 100644
--- a/ext/js/dom/dom-text-scanner.js
+++ b/ext/js/dom/dom-text-scanner.js
@@ -551,10 +551,10 @@ export class DOMTextScanner {
case 'block':
case 'flex':
case 'grid':
- case 'list': // list-item
- case 'table': // table, table-*
+ case 'list': // Also includes: list-item
+ case 'table': // Also includes: table, table-*
return true;
- case 'ruby': // ruby-*
+ case 'ruby': // Also includes: ruby-*
return (pos >= 0);
default:
return false;
diff --git a/ext/js/language/ja/japanese.js b/ext/js/language/ja/japanese.js
index 818daa0b..2c9a1f7f 100644
--- a/ext/js/language/ja/japanese.js
+++ b/ext/js/language/ja/japanese.js
@@ -557,17 +557,17 @@ export function convertHalfWidthKanaToFullWidth(text, sourceMap = null) {
let index = 0;
switch (text.charCodeAt(i + 1)) {
- case 0xff9e: // dakuten
+ case 0xff9e: // Dakuten
index = 1;
break;
- case 0xff9f: // handakuten
+ case 0xff9f: // Handakuten
index = 2;
break;
}
let c2 = mapping[index];
if (index > 0) {
- if (c2 === '-') { // invalid
+ if (c2 === '-') { // Invalid
index = 0;
c2 = mapping[0];
} else {
diff --git a/ext/js/language/translator.js b/ext/js/language/translator.js
index 2ba1ce0d..b2342e8d 100644
--- a/ext/js/language/translator.js
+++ b/ext/js/language/translator.js
@@ -1609,7 +1609,7 @@ export class Translator {
sequence: rawSequence,
rules
} = databaseEntry;
- // cast is safe because getDeinflections filters out deinflection definitions
+ // Cast is safe because getDeinflections filters out deinflection definitions
const contentDefinitions = /** @type {import('dictionary-data').TermGlossaryContent[]} */ (definitions);
const reading = (rawReading.length > 0 ? rawReading : term);
const {index: dictionaryIndex, priority: dictionaryPriority} = this._getDictionaryOrder(dictionary, enabledDictionaryMap);
diff --git a/ext/js/pages/permissions-main.js b/ext/js/pages/permissions-main.js
index 17169c12..3be97b78 100644
--- a/ext/js/pages/permissions-main.js
+++ b/ext/js/pages/permissions-main.js
@@ -43,14 +43,14 @@ async function setupEnvironmentInfo(api) {
* @returns {Promise<boolean>}
*/
async function isAllowedIncognitoAccess() {
- return await new Promise((resolve) => chrome.extension.isAllowedIncognitoAccess(resolve));
+ return await new Promise((resolve) => { chrome.extension.isAllowedIncognitoAccess(resolve); });
}
/**
* @returns {Promise<boolean>}
*/
async function isAllowedFileSchemeAccess() {
- return await new Promise((resolve) => chrome.extension.isAllowedFileSchemeAccess(resolve));
+ return await new Promise((resolve) => { chrome.extension.isAllowedFileSchemeAccess(resolve); });
}
/**
diff --git a/test/fixtures/dom-test.js b/test/fixtures/dom-test.js
index 578b1324..961e0a77 100644
--- a/test/fixtures/dom-test.js
+++ b/test/fixtures/dom-test.js
@@ -28,6 +28,7 @@ function prepareWindow(window) {
// Define innerText setter as an alias for textContent setter
Object.defineProperty(window.HTMLDivElement.prototype, 'innerText', {
+ get() { return this.textContent; },
set(value) { this.textContent = value; }
});
diff --git a/test/language-transformer.test.js b/test/language-transformer.test.js
index 0c8ef08d..7c0da48b 100644
--- a/test/language-transformer.test.js
+++ b/test/language-transformer.test.js
@@ -923,7 +923,7 @@ describe('LanguageTransformer', () => {
{term: 'あかい', source: 'あけえ', rule: 'adj-i', reasons: ['-e']},
{term: 'こわい', source: 'こええ', rule: 'adj-i', reasons: ['-e']},
{term: 'つよい', source: 'つええ', rule: 'adj-i', reasons: ['-e']},
- // small -e
+ // Small -e
{term: 'すごい', source: 'すげぇ', rule: 'adj-i', reasons: ['-e']},
{term: 'やばい', source: 'やべぇ', rule: 'adj-i', reasons: ['-e']},
{term: 'うるさい', source: 'うるせぇ', rule: 'adj-i', reasons: ['-e']},
@@ -1152,7 +1152,6 @@ describe('LanguageTransformer', () => {
languageTransformer.addDescriptor(descriptor);
describe('deinflections', () => {
- // for (const {valid, tests} of data) {
describe.each(data)('$category', ({valid, tests}) => {
for (const {source, term, rule, reasons} of tests) {
const {has} = hasTermReasons(languageTransformer, source, term, rule, reasons);
diff --git a/test/options-util.test.js b/test/options-util.test.js
index a178aecb..3a1b1efb 100644
--- a/test/options-util.test.js
+++ b/test/options-util.test.js
@@ -702,7 +702,7 @@ describe('OptionsUtil', () => {
const match = fileNameRegex.exec(fileName);
if (match !== null) {
updates.push({
- version: Number.parseInt(match[1]),
+ version: Number.parseInt(match[1], 10),
changes: loadDataFile(path.join(templatesDirPath, match[0]))
});
}
@@ -846,7 +846,7 @@ describe('OptionsUtil', () => {
{{~> (lookup . "marker") ~}}
`.trimStart()
},
- // glossary and glossary-brief update
+ // Glossary and glossary-brief update
{
oldVersion: 7,
newVersion: 12,
@@ -1238,7 +1238,7 @@ describe('OptionsUtil', () => {
<<<UPDATE-ADDITIONS>>>
{{~> (lookup . "marker") ~}}`.trimStart()
},
- // block helper update: furigana and furiganaPlain
+ // Block helper update: furigana and furiganaPlain
{
oldVersion: 20,
newVersion: 21,
@@ -1326,7 +1326,7 @@ describe('OptionsUtil', () => {
{{~> (lookup . "marker") ~}}`.trimStart()
},
- // block helper update: formatGlossary
+ // Block helper update: formatGlossary
{
oldVersion: 20,
newVersion: 21,
@@ -1400,7 +1400,7 @@ describe('OptionsUtil', () => {
{{~> (lookup . "marker") ~}}`.trimStart()
},
- // block helper update: set and get
+ // Block helper update: set and get
{
oldVersion: 20,
newVersion: 21,
@@ -1502,7 +1502,7 @@ describe('OptionsUtil', () => {
{{~> (lookup . "marker") ~}}`.trimStart()
},
- // block helper update: hasMedia and getMedia
+ // Block helper update: hasMedia and getMedia
{
oldVersion: 20,
newVersion: 21,
@@ -1584,7 +1584,7 @@ describe('OptionsUtil', () => {
{{~> (lookup . "marker") ~}}`.trimStart()
},
- // block helper update: pronunciation
+ // Block helper update: pronunciation
{
oldVersion: 20,
newVersion: 21,
diff --git a/test/playwright/integration.spec.js b/test/playwright/integration.spec.js
index 170714a1..06af3fd2 100644
--- a/test/playwright/integration.spec.js
+++ b/test/playwright/integration.spec.js
@@ -31,13 +31,13 @@ import {
test.beforeEach(async ({context}) => {
// Wait for the on-install welcome.html tab to load, which becomes the foreground tab
const welcome = await context.waitForEvent('page');
- await welcome.close(); // close the welcome tab so our main tab becomes the foreground tab -- otherwise, the screenshot can hang
+ await welcome.close(); // Close the welcome tab so our main tab becomes the foreground tab -- otherwise, the screenshot can hang
});
test('search clipboard', async ({page, extensionId}) => {
await page.goto(`chrome-extension://${extensionId}/search.html`);
await page.locator('#search-option-clipboard-monitor-container > label').click();
- await page.waitForTimeout(200); // race
+ await page.waitForTimeout(200); // Race
await writeToClipboardFromPage(page, 'あ');
await expect(page.locator('#search-textbox')).toHaveValue('あ');
diff --git a/test/playwright/playwright-util.js b/test/playwright/playwright-util.js
index b364c80b..b9a4831a 100644
--- a/test/playwright/playwright-util.js
+++ b/test/playwright/playwright-util.js
@@ -28,7 +28,7 @@ export const test = base.extend({
context: async ({}, use) => {
const pathToExtension = path.join(root, 'ext');
const context = await chromium.launchPersistentContext('', {
- // headless: false,
+ // Disabled: headless: false,
args: [
'--headless=new',
`--disable-extensions-except=${pathToExtension}`,
diff --git a/test/playwright/visual.spec.js b/test/playwright/visual.spec.js
index fc8bb8df..157cedc7 100644
--- a/test/playwright/visual.spec.js
+++ b/test/playwright/visual.spec.js
@@ -22,7 +22,7 @@ import {expect, root, test} from './playwright-util.js';
test.beforeEach(async ({context}) => {
// Wait for the on-install welcome.html tab to load, which becomes the foreground tab
const welcome = await context.waitForEvent('page');
- welcome.close(); // close the welcome tab so our main tab becomes the foreground tab -- otherwise, the screenshot can hang
+ welcome.close(); // Close the welcome tab so our main tab becomes the foreground tab -- otherwise, the screenshot can hang
});
test('visual', async ({page, extensionId}) => {
@@ -63,9 +63,9 @@ test('visual', async ({page, extensionId}) => {
if (typeof popup_frame === 'undefined') {
frame_attached = page.waitForEvent('frameattached');
}
- await page.mouse.move(box.x + offset.x, box.y + offset.y, {steps: 10}); // hover over the test
+ await page.mouse.move(box.x + offset.x, box.y + offset.y, {steps: 10}); // Hover over the test
if (typeof popup_frame === 'undefined') {
- popup_frame = await frame_attached; // wait for popup to be attached
+ popup_frame = await frame_attached; // Wait for popup to be attached
}
try {
// Some tests don't have a popup, so don't fail if it's not there
@@ -75,11 +75,11 @@ test('visual', async ({page, extensionId}) => {
console.log(test_name + ' has no popup');
}
- await page.bringToFront(); // bring the page to the foreground so the screenshot doesn't hang; for some reason the frames result in page being in the background
+ await page.bringToFront(); // Bring the page to the foreground so the screenshot doesn't hang; for some reason the frames result in page being in the background
await expect.soft(page).toHaveScreenshot(test_name + '.png');
- await page.mouse.click(0, 0); // click away so popup disappears
- await (await /** @type {import('@playwright/test').Frame} */ (popup_frame).frameElement()).waitForElementState('hidden'); // wait for popup to disappear
+ await page.mouse.click(0, 0); // Click away so popup disappears
+ await (await /** @type {import('@playwright/test').Frame} */ (popup_frame).frameElement()).waitForElementState('hidden'); // Wait for popup to disappear
};
// Test document 1
diff --git a/test/profile-conditions-util.test.js b/test/profile-conditions-util.test.js
index 6de5ad1d..590e5873 100644
--- a/test/profile-conditions-util.test.js
+++ b/test/profile-conditions-util.test.js
@@ -250,7 +250,7 @@ describe('Profile conditions utilities', () => {
]
},
- // url tests
+ // Url tests
{
conditionGroups: [
{
@@ -606,7 +606,7 @@ describe('Profile conditions utilities', () => {
]
},
- // flags tests
+ // Flags tests
{
conditionGroups: [
{
diff --git a/test/utilities/translator.js b/test/utilities/translator.js
index b77bfb39..f452e688 100644
--- a/test/utilities/translator.js
+++ b/test/utilities/translator.js
@@ -16,6 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+// eslint-disable-next-line no-template-curly-in-string
const placeholder = '${title}';
/**
diff --git a/types/ext/application.d.ts b/types/ext/application.d.ts
index 903c8e45..930220f0 100644
--- a/types/ext/application.d.ts
+++ b/types/ext/application.d.ts
@@ -15,11 +15,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import type {TokenString} from './core';
+import type {TokenString, EventNames, EventArgument as BaseEventArgument} from './core';
import type {SearchMode} from './display';
import type {FrameEndpointReadyDetails, FrameEndpointConnectedDetails} from './frame-client';
import type {DatabaseUpdateType, DatabaseUpdateCause} from './backend';
-import type {EventNames, EventArgument as BaseEventArgument} from './core';
import type {
ApiMap as BaseApiMap,
ApiHandler as BaseApiHandler,