Reduce Community lint type-safety warnings

This commit is contained in:
vorotamoroz
2026-07-20 18:08:09 +00:00
parent 2cf535332b
commit 104eeadb4b
29 changed files with 664 additions and 318 deletions
@@ -23,6 +23,7 @@ import { serialized } from "octagonal-wheels/concurrency/lock";
import type { ReactiveSource } from "octagonal-wheels/dataobject/reactive_v2";
import type { LiveSyncBaseCore } from "@/LiveSyncBaseCore";
import { isNotFoundError } from "@vrtmrz/livesync-commonlib/compat/common/utils.doc";
import type PouchDB from "pouchdb-core";
const KV_KEY_REPLICATION_RESULT_PROCESSOR_SNAPSHOT = "replicationResultProcessorSnapshot";
type ReplicateResultProcessorState = {
@@ -12,10 +12,22 @@ import type {
UXFileInfoStub,
UXFolderInfo,
UXInternalFileInfoStub,
UXStat,
} from "@vrtmrz/livesync-commonlib/compat/common/types";
import type { LiveSyncCore } from "@/main.ts";
import type { FileAccessObsidian } from "@/serviceModules/FileAccessObsidian.ts";
function isUXStat(value: unknown): value is UXStat {
if (typeof value !== "object" || value === null) return false;
const stat = value as Partial<UXStat>;
return (
typeof stat.size === "number" &&
typeof stat.ctime === "number" &&
typeof stat.mtime === "number" &&
(stat.type === "file" || stat.type === "folder")
);
}
export async function TFileToUXFileInfo(
core: LiveSyncCore,
file: TFile,
@@ -55,8 +67,8 @@ export async function InternalFileToUXFileInfo(
prefix: string = ICHeader
): Promise<UXFileInfo> {
const name = fullPath.split("/").pop() as string;
const stat = await vaultAccess.tryAdapterStat(fullPath);
if (stat == null) throw new Error(`File not found: ${fullPath}`);
const stat: unknown = await vaultAccess.tryAdapterStat(fullPath);
if (!isUXStat(stat)) throw new Error(`File not found: ${fullPath}`);
if (stat.type == "folder") throw new Error(`File not found: ${fullPath}`);
const file = await vaultAccess.adapterReadAuto(fullPath);
@@ -25,6 +25,15 @@ function requestTimeout(timeoutInMs: number = 0): Promise<never> {
});
}
function normaliseRequestBody(body: unknown): string | ArrayBuffer | undefined {
if (typeof body === "string" || body instanceof ArrayBuffer) return body;
if (ArrayBuffer.isView(body)) {
if (body.buffer instanceof ArrayBuffer) return body.buffer;
return new Uint8Array(body.buffer).slice().buffer;
}
return undefined;
}
/**
* This is close to origin implementation of FetchHttpHandler
* https://github.com/aws/aws-sdk-js-v3/blob/main/packages/fetch-http-handler/src/fetch-http-handler.ts
@@ -64,7 +73,7 @@ export class ObsHttpHandler extends FetchHttpHandler {
urlObj.host = this.reverseProxyNoSignUrl;
url = urlObj.href;
}
const body = method === "GET" || method === "HEAD" ? undefined : request.body;
const body: unknown = method === "GET" || method === "HEAD" ? undefined : request.body;
const transformedHeaders: Record<string, string> = {};
for (const key of Object.keys(request.headers)) {
@@ -80,10 +89,7 @@ export class ObsHttpHandler extends FetchHttpHandler {
contentType = transformedHeaders["content-type"];
}
let transformedBody = body;
if (ArrayBuffer.isView(body)) {
transformedBody = new Uint8Array(body.buffer).buffer;
}
const transformedBody = normaliseRequestBody(body);
const param: RequestUrlParam = {
body: transformedBody,
@@ -22,6 +22,7 @@ import {
loadDocumentHistoryPreference,
saveDocumentHistoryPreference,
} from "./documentHistoryPreferences.ts";
import type PouchDB from "pouchdb-core";
function isImage(path: string) {
const ext = path.split(".").splice(-1)[0].toLowerCase();
@@ -8,7 +8,7 @@ import { globalSlipBoard } from "@vrtmrz/livesync-commonlib/compat/bureau/bureau
export type MergeDialogResult = typeof CANCELLED | typeof LEAVE_TO_SUBSEQUENT | string;
declare global {
interface Slips extends LSSlips {
interface Slips {
"conflict-resolved": typeof CANCELLED | MergeDialogResult;
}
}
@@ -2,8 +2,12 @@
import { isObjectDifferent } from "octagonal-wheels/object";
import { EVENT_SETTING_SAVED, eventHub } from "@/common/events";
import { fireAndForget } from "octagonal-wheels/promises";
import { DEFAULT_SETTINGS, type FilePathWithPrefix, type ObsidianLiveSyncSettings } from "@vrtmrz/livesync-commonlib/compat/common/types";
import { parseYaml, stringifyYaml } from "@/deps";
import {
DEFAULT_SETTINGS,
type FilePathWithPrefix,
type ObsidianLiveSyncSettings,
} from "@vrtmrz/livesync-commonlib/compat/common/types";
import { parseYaml, stringifyYaml, type Editor, type MarkdownView } from "@/deps";
import { LOG_LEVEL_DEBUG, LOG_LEVEL_INFO, LOG_LEVEL_NOTICE, LOG_LEVEL_VERBOSE } from "octagonal-wheels/common/logger";
import { AbstractModule } from "@/modules/AbstractModule.ts";
import type { ServiceContext } from "@vrtmrz/livesync-commonlib/context";
@@ -28,7 +32,7 @@ export class ModuleObsidianSettingsAsMarkdown extends AbstractModule {
this.addCommand({
id: "livesync-import-config",
name: "Parse setting file",
editorCheckCallback: (checking, editor, ctx) => {
editorCheckCallback: (checking: boolean, editor: Editor, ctx: MarkdownView) => {
if (checking) {
const doc = editor.getValue();
const ret = this.extractSettingFromWholeText(doc);
@@ -104,7 +108,11 @@ export class ModuleObsidianSettingsAsMarkdown extends AbstractModule {
const { body } = await this.parseSettingFromMarkdown(filename);
let newSetting = {} as Partial<ObsidianLiveSyncSettings>;
try {
newSetting = parseYaml(body);
const parsed: unknown = parseYaml(body);
if (typeof parsed !== "object" || parsed === null) {
throw new TypeError("The YAML settings must contain an object");
}
newSetting = parsed;
} catch (ex) {
this._log("Could not parse YAML", LOG_LEVEL_NOTICE);
this._log(ex, LOG_LEVEL_VERBOSE);
@@ -3,6 +3,7 @@ import { AbstractObsidianModule } from "@/modules/AbstractObsidianModule.ts";
// import { PouchDB } from "../../lib/src/pouchdb/pouchdb-browser";
import { EVENT_REQUEST_OPEN_SETTING_WIZARD, EVENT_REQUEST_OPEN_SETTINGS, eventHub } from "@/common/events.ts";
import type { LiveSyncCore } from "@/main.ts";
import { openObsidianSettings } from "@/common/obsidianSettings.ts";
export class ModuleObsidianSettingDialogue extends AbstractObsidianModule {
settingTab!: ObsidianLiveSyncSettingTab;
@@ -20,11 +21,7 @@ export class ModuleObsidianSettingDialogue extends AbstractObsidianModule {
}
openSetting() {
// Undocumented API
//@ts-ignore
this.app.setting.open();
//@ts-ignore
this.app.setting.openTabById("obsidian-livesync");
openObsidianSettings(this.app, "obsidian-livesync");
}
get appId() {
@@ -63,6 +63,7 @@ import { paneMaintenance } from "./PaneMaintenance.ts";
import { compatGlobal } from "@vrtmrz/livesync-commonlib/compat/common/coreEnvFunctions";
import { JournalSyncCore } from "@vrtmrz/livesync-commonlib/compat/replication/journal/JournalSyncCore";
import { MinioStorageAdapter } from "@vrtmrz/livesync-commonlib/compat/replication/journal/objectstore/MinioStorageAdapter";
import { closeObsidianSettings } from "@/common/obsidianSettings.ts";
// For creating a document
// const toc = new Set<string>();
@@ -99,6 +100,14 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
// Buffered Settings for comparing.
initialSettings?: typeof this.editingSettings;
private copySettingValue(target: object | undefined, source: object, key: AllSettingItemKey): void {
if (!target) {
throw new Error("Initial settings have not been loaded");
}
const value: unknown = Reflect.get(source, key);
Reflect.set(target, key, value);
}
/**
* Apply editing setting to the plug-in.
* @param keys setting keys for applying
@@ -111,10 +120,8 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
// this.initialSettings[k] = this.editingSettings[k];
continue;
}
//@ts-ignore
this.core.settings[k] = this.editingSettings[k];
//@ts-ignore
this.initialSettings[k] = this.core.settings[k];
this.copySettingValue(this.core.settings, this.editingSettings, k);
this.copySettingValue(this.initialSettings, this.core.settings, k);
}
keys.forEach((e) => this.refreshSetting(e));
}
@@ -149,14 +156,11 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
appliedKeys.push(k);
if (k in OnDialogSettingsDefault) {
await this.saveLocalSetting(k as keyof OnDialogSettings);
//@ts-ignore
this.initialSettings[k] = this.editingSettings[k];
this.copySettingValue(this.initialSettings, this.editingSettings, k);
continue;
}
//@ts-ignore
this.core.settings[k] = this.editingSettings[k];
//@ts-ignore
this.initialSettings[k] = this.core.settings[k];
this.copySettingValue(this.core.settings, this.editingSettings, k);
this.copySettingValue(this.initialSettings, this.core.settings, k);
hasChanged = true;
}
@@ -234,15 +238,11 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
const localSetting = this.reloadAllLocalSettings();
if (key in this.core.settings) {
if (key in localSetting) {
//@ts-ignore
this.initialSettings[key] = localSetting[key];
//@ts-ignore
this.editingSettings[key] = localSetting[key];
this.copySettingValue(this.initialSettings, localSetting, key);
this.copySettingValue(this.editingSettings, localSetting, key);
} else {
//@ts-ignore
this.initialSettings[key] = this.core.settings[key];
//@ts-ignore
this.editingSettings[key] = this.initialSettings[key];
this.copySettingValue(this.initialSettings, this.core.settings, key);
this.copySettingValue(this.editingSettings, this.initialSettings ?? {}, key);
}
}
this.editingSettings = { ...this.editingSettings, ...this.computeAllLocalSettings() };
@@ -308,8 +308,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
}
closeSetting() {
//@ts-ignore :
this.plugin.app.setting.close();
closeObsidianSettings(this.plugin.app);
}
handleElement(element: HTMLElement, func: OnUpdateFunc) {
@@ -1,7 +1,7 @@
import { MarkdownRenderer } from "@/deps.ts";
import { fireAndForget } from "octagonal-wheels/promises";
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
//@ts-ignore
declare const UPDATE_INFO: string;
const updateInformation: string = UPDATE_INFO || "";
export function paneChangeLog(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement): void {
@@ -1,12 +1,18 @@
import { requestToCouchDBWithCredentials } from "@/common/utils";
import { $msg } from "@vrtmrz/livesync-commonlib/compat/common/i18n";
import { LOG_LEVEL_INFO, LOG_LEVEL_NOTICE, LOG_LEVEL_VERBOSE, Logger } from "@vrtmrz/livesync-commonlib/compat/common/logger";
import {
LOG_LEVEL_INFO,
LOG_LEVEL_NOTICE,
LOG_LEVEL_VERBOSE,
Logger,
} from "@vrtmrz/livesync-commonlib/compat/common/logger";
import type { ObsidianLiveSyncSettings } from "@vrtmrz/livesync-commonlib/compat/common/types";
import { fireAndForget, parseHeaderValues } from "@vrtmrz/livesync-commonlib/compat/common/utils";
import { isCloudantURI } from "@vrtmrz/livesync-commonlib/compat/pouchdb/utils_couchdb";
import { generateCredentialObject } from "@vrtmrz/livesync-commonlib/compat/replication/httplib";
import { compatGlobal } from "@vrtmrz/livesync-commonlib/compat/common/coreEnvFunctions";
import { isUnauthorizedError } from "@vrtmrz/livesync-commonlib/compat/common/utils.doc";
import { normaliseCouchDBConfiguration } from "@/common/couchdbConfiguration";
export const checkConfig = async (
checkResultDiv: HTMLDivElement | undefined,
@@ -43,7 +49,7 @@ export const checkConfig = async (
undefined,
customHeaders
);
const responseConfig = r.json;
const responseConfig = normaliseCouchDBConfiguration(r.json as unknown);
const addConfigFixButton = (title: string, key: string, value: string) => {
if (!checkResultDiv) return;
@@ -7,6 +7,7 @@ import { isCloudantURI } from "@vrtmrz/livesync-commonlib/compat/pouchdb/utils_c
import { generateCredentialObject } from "@vrtmrz/livesync-commonlib/compat/replication/httplib";
import { compatGlobal } from "@vrtmrz/livesync-commonlib/compat/common/coreEnvFunctions";
import { isUnauthorizedError } from "@vrtmrz/livesync-commonlib/compat/common/utils.doc";
import { normaliseCouchDBConfiguration } from "@/common/couchdbConfiguration";
export type ResultMessage = { message: string; classes: string[] };
export type ResultErrorMessage = { message: string; result: "error"; classes: string[] };
@@ -115,7 +116,7 @@ export const checkConfig = async (editingSettings: ObsidianLiveSyncSettings) =>
undefined,
customHeaders
);
const responseConfig = r.json;
const responseConfig = normaliseCouchDBConfiguration(r.json as unknown);
addMessage($msg("obsidianLiveSyncSettingTab.msgNotice"), ["ob-btn-config-head"]);
addMessage($msg("obsidianLiveSyncSettingTab.msgIfConfigNotPersistent"), ["ob-btn-config-info"]);
addMessage($msg("obsidianLiveSyncSettingTab.msgConfigCheck"), ["ob-btn-config-head"]);
@@ -10,10 +10,9 @@ import {
} from "@vrtmrz/livesync-commonlib/compat/services/base/SettingService";
import type { ObsidianServiceContext } from "@/modules/services/ObsidianServiceContext";
export function normaliseObsidianSettingsData(
data: ObsidianLiveSyncSettings | null | undefined
): ObsidianLiveSyncSettings | undefined {
return data ?? undefined;
export function normaliseObsidianSettingsData(data: unknown): ObsidianLiveSyncSettings | undefined {
if (typeof data !== "object" || data === null || Array.isArray(data)) return undefined;
return data as ObsidianLiveSyncSettings;
}
export class ObsidianSettingService<T extends ObsidianServiceContext> extends SettingService<T> {