mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-10-21 08:42:31 +00:00
Improve typings
Remove `DEV` blocks
This commit is contained in:
@@ -97,7 +97,7 @@ export const obsidianRules = {
|
|||||||
// -- Plugin specific overrides
|
// -- Plugin specific overrides
|
||||||
"obsidianmd/rule-custom-message": "off",
|
"obsidianmd/rule-custom-message": "off",
|
||||||
"obsidianmd/ui/sentence-case": "off",
|
"obsidianmd/ui/sentence-case": "off",
|
||||||
"obsidianmd/no-plugin-as-component": "off",
|
"obsidianmd/no-plugin-as-component": "warn",
|
||||||
|
|
||||||
// -- Temporary overrides for migration
|
// -- Temporary overrides for migration
|
||||||
"obsidianmd/no-static-styles-assignment": "off",
|
"obsidianmd/no-static-styles-assignment": "off",
|
||||||
|
|||||||
+1
-2
@@ -86,8 +86,6 @@ export default defineConfig([
|
|||||||
parserOptions: {
|
parserOptions: {
|
||||||
parser: tsParser,
|
parser: tsParser,
|
||||||
extraFileExtensions: [".svelte"],
|
extraFileExtensions: [".svelte"],
|
||||||
project: "./tsconfig.json",
|
|
||||||
rootDir: "./",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
@@ -96,6 +94,7 @@ export default defineConfig([
|
|||||||
// it may improve in the future with some options as like ["error", { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }],]
|
// it may improve in the future with some options as like ["error", { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }],]
|
||||||
"no-unused-vars": "off",
|
"no-unused-vars": "off",
|
||||||
...obsidianRules,
|
...obsidianRules,
|
||||||
|
"obsidianmd/no-plugin-as-component": "off",
|
||||||
...ImportAliasRules("."),
|
...ImportAliasRules("."),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import { ModuleLiveSyncMain } from "./modules/main/ModuleLiveSyncMain";
|
|||||||
import type { ServiceModules } from "./lib/src/interfaces/ServiceModule";
|
import type { ServiceModules } from "./lib/src/interfaces/ServiceModule";
|
||||||
import { ModuleBasicMenu } from "./modules/essential/ModuleBasicMenu";
|
import { ModuleBasicMenu } from "./modules/essential/ModuleBasicMenu";
|
||||||
import { usePrepareDatabaseForUse } from "./lib/src/serviceFeatures/prepareDatabaseForUse";
|
import { usePrepareDatabaseForUse } from "./lib/src/serviceFeatures/prepareDatabaseForUse";
|
||||||
|
import type { Constructor } from "@lib/common/utils.type";
|
||||||
|
|
||||||
export class LiveSyncBaseCore<
|
export class LiveSyncBaseCore<
|
||||||
T extends ServiceContext = ServiceContext,
|
T extends ServiceContext = ServiceContext,
|
||||||
@@ -120,7 +121,7 @@ export class LiveSyncBaseCore<
|
|||||||
* @param constructor
|
* @param constructor
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
getModule<T extends AbstractModule>(constructor: new (...args: any[]) => T): T {
|
getModule<T extends AbstractModule>(constructor: Constructor<T>): T {
|
||||||
for (const module of this.modules) {
|
for (const module of this.modules) {
|
||||||
if (module.constructor === constructor) return module as T;
|
if (module.constructor === constructor) return module as T;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,8 +232,8 @@ async function createDefaultSettingsFile(options: CLIOptions) {
|
|||||||
const targetPath = options.settingsPath
|
const targetPath = options.settingsPath
|
||||||
? path.resolve(options.settingsPath)
|
? path.resolve(options.settingsPath)
|
||||||
: options.commandArgs[0]
|
: options.commandArgs[0]
|
||||||
? path.resolve(options.commandArgs[0])
|
? path.resolve(options.commandArgs[0])
|
||||||
: path.resolve(process.cwd(), "data.json");
|
: path.resolve(process.cwd(), "data.json");
|
||||||
|
|
||||||
if (!options.force) {
|
if (!options.force) {
|
||||||
try {
|
try {
|
||||||
@@ -323,8 +323,8 @@ export async function main() {
|
|||||||
options.command === "mirror" && options.commandArgs[0]
|
options.command === "mirror" && options.commandArgs[0]
|
||||||
? path.resolve(options.commandArgs[0])
|
? path.resolve(options.commandArgs[0])
|
||||||
: options.vaultPath
|
: options.vaultPath
|
||||||
? path.resolve(options.vaultPath)
|
? path.resolve(options.vaultPath)
|
||||||
: databasePath!;
|
: databasePath!;
|
||||||
|
|
||||||
// Check if vault directory exists
|
// Check if vault directory exists
|
||||||
try {
|
try {
|
||||||
@@ -458,8 +458,8 @@ export async function main() {
|
|||||||
if (rules.shouldIgnore(targetPath)) {
|
if (rules.shouldIgnore(targetPath)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// undefined = pass through to next handler in chain
|
// At least this handler think it is a target file, but other handlers may still veto it.
|
||||||
return undefined;
|
return true;
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -557,7 +557,7 @@ export async function main() {
|
|||||||
|
|
||||||
if (options.command === "daemon" && result) {
|
if (options.command === "daemon" && result) {
|
||||||
// Keep the process running
|
// Keep the process running
|
||||||
await new Promise(() => { });
|
await new Promise(() => {});
|
||||||
} else {
|
} else {
|
||||||
await core.services.control.onUnload();
|
await core.services.control.onUnload();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ class CLIWatchAdapter implements IStorageEventWatchAdapter {
|
|||||||
private basePath: string,
|
private basePath: string,
|
||||||
private ignoreRules?: IgnoreRules,
|
private ignoreRules?: IgnoreRules,
|
||||||
private watchEnabled: boolean = false
|
private watchEnabled: boolean = false
|
||||||
) { }
|
) {}
|
||||||
|
|
||||||
private _toNodeFile(filePath: string, stats: Stats | undefined): NodeFile {
|
private _toNodeFile(filePath: string, stats: Stats | undefined): NodeFile {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -4,10 +4,4 @@ import * as nodeFsPromises from "node:fs/promises";
|
|||||||
import * as nodePath from "node:path";
|
import * as nodePath from "node:path";
|
||||||
import * as nodeReadlinePromises from "node:readline/promises";
|
import * as nodeReadlinePromises from "node:readline/promises";
|
||||||
import type { Stats } from "node:fs";
|
import type { Stats } from "node:fs";
|
||||||
export {
|
export { nodeFs as fs, nodeFsPromises as fsPromises, nodePath as path, nodeReadlinePromises as readline, type Stats };
|
||||||
nodeFs as fs,
|
|
||||||
nodeFsPromises as fsPromises,
|
|
||||||
nodePath as path,
|
|
||||||
nodeReadlinePromises as readline,
|
|
||||||
type Stats,
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -77,9 +77,7 @@ export class BackgroundCliProcess {
|
|||||||
if (this.combined.includes(needle)) return;
|
if (this.combined.includes(needle)) return;
|
||||||
const status = await Promise.race([
|
const status = await Promise.race([
|
||||||
this.child.status.then((s) => ({ type: "status" as const, status: s })),
|
this.child.status.then((s) => ({ type: "status" as const, status: s })),
|
||||||
new Promise<{ type: "tick" }>((resolve) =>
|
new Promise<{ type: "tick" }>((resolve) => setTimeout(() => resolve({ type: "tick" }), 100)),
|
||||||
setTimeout(() => resolve({ type: "tick" }), 100)
|
|
||||||
),
|
|
||||||
]);
|
]);
|
||||||
if (status.type === "status") {
|
if (status.type === "status") {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ Deno.test("CLI file operations: push / cat / ls / info / rm / resolve / cat-rev
|
|||||||
assertEquals(data.path, REMOTE_PATH, "info .path mismatch");
|
assertEquals(data.path, REMOTE_PATH, "info .path mismatch");
|
||||||
assertEquals(data.filename, REMOTE_PATH.split("/").at(-1), "info .filename mismatch");
|
assertEquals(data.filename, REMOTE_PATH.split("/").at(-1), "info .filename mismatch");
|
||||||
assert(typeof data.size === "number" && data.size >= 0, `info .size invalid: ${data.size}`);
|
assert(typeof data.size === "number" && data.size >= 0, `info .size invalid: ${data.size}`);
|
||||||
assert(typeof data.chunks === "number" && (data.chunks) >= 1, `info .chunks invalid: ${data.chunks}`);
|
assert(typeof data.chunks === "number" && data.chunks >= 1, `info .chunks invalid: ${data.chunks}`);
|
||||||
assertEquals(data.conflicts, "N/A", "info .conflicts should be N/A");
|
assertEquals(data.conflicts, "N/A", "info .conflicts should be N/A");
|
||||||
console.log("[PASS] info output format matched");
|
console.log("[PASS] info output format matched");
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ import { defineConfig } from "vite";
|
|||||||
import { svelte } from "@sveltejs/vite-plugin-svelte";
|
import { svelte } from "@sveltejs/vite-plugin-svelte";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { readFileSync } from "node:fs";
|
import { readFileSync } from "node:fs";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
const resolve = (...args: string[]) => path.resolve(...args).replace(/\\/g, "/");
|
const resolve = (...args: string[]) => path.resolve(...args).replace(/\\/g, "/");
|
||||||
const packageJson = JSON.parse(readFileSync("../../../package.json", "utf-8"));
|
const repoRoot = path.resolve(__dirname, "../../..");
|
||||||
const manifestJson = JSON.parse(readFileSync("../../../manifest.json", "utf-8"));
|
const packageJson = JSON.parse(readFileSync(path.resolve(repoRoot, "package.json"), "utf-8"));
|
||||||
|
const manifestJson = JSON.parse(readFileSync(path.resolve(repoRoot, "manifest.json"), "utf-8"));
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
const defaultExternal = [
|
const defaultExternal = [
|
||||||
"obsidian",
|
"obsidian",
|
||||||
|
|||||||
@@ -27,6 +27,6 @@
|
|||||||
"@lib/*": ["../../lib/src/*"]
|
"@lib/*": ["../../lib/src/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["*.ts", "**/*.ts", "**/*.tsx"],
|
"include": ["*.ts", "**/*.ts", "**/*.tsx", "**/*.svelte"],
|
||||||
"exclude": ["node_modules", "dist"]
|
"exclude": ["node_modules", "dist"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ export class VaultHistoryStore {
|
|||||||
|
|
||||||
async getVaultHistory(): Promise<VaultHistoryItem[]> {
|
async getVaultHistory(): Promise<VaultHistoryItem[]> {
|
||||||
return this.withStore("readonly", async (store) => {
|
return this.withStore("readonly", async (store) => {
|
||||||
const keys = (await this.requestAsPromise(store.getAllKeys()));
|
const keys = await this.requestAsPromise(store.getAllKeys());
|
||||||
const values = (await this.requestAsPromise(store.getAll())) as unknown[];
|
const values = (await this.requestAsPromise(store.getAll())) as unknown[];
|
||||||
const items: VaultHistoryItem[] = [];
|
const items: VaultHistoryItem[] = [];
|
||||||
for (let i = 0; i < keys.length; i++) {
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ import { svelte } from "@sveltejs/vite-plugin-svelte";
|
|||||||
import istanbul from "vite-plugin-istanbul";
|
import istanbul from "vite-plugin-istanbul";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { readFileSync } from "node:fs";
|
import { readFileSync } from "node:fs";
|
||||||
const packageJson = JSON.parse(readFileSync("../../../package.json", "utf-8"));
|
import { fileURLToPath } from "node:url";
|
||||||
const manifestJson = JSON.parse(readFileSync("../../../manifest.json", "utf-8"));
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
const enableCoverage = process.env.PW_COVERAGE === "1";
|
|
||||||
const repoRoot = path.resolve(__dirname, "../../..");
|
const repoRoot = path.resolve(__dirname, "../../..");
|
||||||
|
const packageJson = JSON.parse(readFileSync(path.resolve(repoRoot, "package.json"), "utf-8"));
|
||||||
|
const manifestJson = JSON.parse(readFileSync(path.resolve(repoRoot, "manifest.json"), "utf-8"));
|
||||||
|
const enableCoverage = process.env.PW_COVERAGE === "1";
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { deleteDB, type IDBPDatabase, openDB } from "idb";
|
|||||||
import type { KeyValueDatabase } from "@lib/interfaces/KeyValueDatabase.ts";
|
import type { KeyValueDatabase } from "@lib/interfaces/KeyValueDatabase.ts";
|
||||||
import { serialized } from "octagonal-wheels/concurrency/lock";
|
import { serialized } from "octagonal-wheels/concurrency/lock";
|
||||||
import { Logger } from "octagonal-wheels/common/logger";
|
import { Logger } from "octagonal-wheels/common/logger";
|
||||||
const databaseCache: { [key: string]: IDBPDatabase<any> } = {};
|
const databaseCache: { [key: string]: IDBPDatabase<unknown> } = {};
|
||||||
export { OpenKeyValueDatabase } from "./KeyValueDBv2.ts";
|
export { OpenKeyValueDatabase } from "./KeyValueDBv2.ts";
|
||||||
|
|
||||||
export const _OpenKeyValueDatabase = async (dbKey: string): Promise<KeyValueDatabase> => {
|
export const _OpenKeyValueDatabase = async (dbKey: string): Promise<KeyValueDatabase> => {
|
||||||
@@ -11,7 +11,7 @@ export const _OpenKeyValueDatabase = async (dbKey: string): Promise<KeyValueData
|
|||||||
delete databaseCache[dbKey];
|
delete databaseCache[dbKey];
|
||||||
}
|
}
|
||||||
const storeKey = dbKey;
|
const storeKey = dbKey;
|
||||||
let db: IDBPDatabase<any> | null = null;
|
let db: IDBPDatabase<unknown> | null = null;
|
||||||
const _openDB = () => {
|
const _openDB = () => {
|
||||||
return serialized("keyvaluedb-" + dbKey, async () => {
|
return serialized("keyvaluedb-" + dbKey, async () => {
|
||||||
const dbInstance = await openDB(dbKey, 1, {
|
const dbInstance = await openDB(dbKey, 1, {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export async function OpenKeyValueDatabase(dbKey: string): Promise<KeyValueDatab
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class IDBKeyValueDatabase implements KeyValueDatabase {
|
export class IDBKeyValueDatabase implements KeyValueDatabase {
|
||||||
protected _dbPromise: Promise<IDBPDatabase<any>> | null = null;
|
protected _dbPromise: Promise<IDBPDatabase<unknown>> | null = null;
|
||||||
protected dbKey: string;
|
protected dbKey: string;
|
||||||
protected storeKey: string;
|
protected storeKey: string;
|
||||||
protected _isDestroyed: boolean = false;
|
protected _isDestroyed: boolean = false;
|
||||||
@@ -104,7 +104,7 @@ export class IDBKeyValueDatabase implements KeyValueDatabase {
|
|||||||
this.destroyedPromise = Promise.resolve();
|
this.destroyedPromise = Promise.resolve();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
get DB(): Promise<IDBPDatabase<any>> {
|
get DB(): Promise<IDBPDatabase<unknown>> {
|
||||||
if (this._isDestroyed) {
|
if (this._isDestroyed) {
|
||||||
return Promise.reject(new Error("Database is destroyed"));
|
return Promise.reject(new Error("Database is destroyed"));
|
||||||
}
|
}
|
||||||
@@ -117,7 +117,7 @@ export class IDBKeyValueDatabase implements KeyValueDatabase {
|
|||||||
}
|
}
|
||||||
async get<U>(key: IDBValidKey): Promise<U> {
|
async get<U>(key: IDBValidKey): Promise<U> {
|
||||||
const db = await this.DB;
|
const db = await this.DB;
|
||||||
return await db.get(this.storeKey, key);
|
return (await db.get(this.storeKey, key)) as U;
|
||||||
}
|
}
|
||||||
async set<U>(key: IDBValidKey, value: U): Promise<IDBValidKey> {
|
async set<U>(key: IDBValidKey, value: U): Promise<IDBValidKey> {
|
||||||
const db = await this.DB;
|
const db = await this.DB;
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import { eventHub, EVENT_PLUGIN_UNLOADED } from "./events";
|
|||||||
import type { NecessaryServices } from "@lib/interfaces/ServiceModule";
|
import type { NecessaryServices } from "@lib/interfaces/ServiceModule";
|
||||||
type PeriodicProcessorHost = NecessaryServices<"API" | "control", never>;
|
type PeriodicProcessorHost = NecessaryServices<"API" | "control", never>;
|
||||||
export class PeriodicProcessor {
|
export class PeriodicProcessor {
|
||||||
_process: () => Promise<any>;
|
_process: () => Promise<unknown>;
|
||||||
_timer?: number = undefined;
|
_timer?: number = undefined;
|
||||||
_core: PeriodicProcessorHost;
|
_core: PeriodicProcessorHost;
|
||||||
constructor(core: PeriodicProcessorHost, process: () => Promise<any>) {
|
constructor(core: PeriodicProcessorHost, process: () => Promise<unknown>) {
|
||||||
// this._plugin = plugin;
|
// this._plugin = plugin;
|
||||||
this._core = core;
|
this._core = core;
|
||||||
this._process = process;
|
this._process = process;
|
||||||
|
|||||||
@@ -9,16 +9,16 @@ import { isCloudantURI } from "@lib/pouchdb/utils_couchdb";
|
|||||||
import { compatGlobal } from "@lib/common/coreEnvFunctions";
|
import { compatGlobal } from "@lib/common/coreEnvFunctions";
|
||||||
import { manifestVersion, packageVersion } from "@lib/common/coreEnvVars";
|
import { manifestVersion, packageVersion } from "@lib/common/coreEnvVars";
|
||||||
import type { LiveSyncBaseCore } from "@/LiveSyncBaseCore";
|
import type { LiveSyncBaseCore } from "@/LiveSyncBaseCore";
|
||||||
function redactObject(obj: Record<string, any>, dotted: string, redactedValue = "REDACTED") {
|
function redactObject(obj: Record<string, unknown>, dotted: string, redactedValue = "REDACTED") {
|
||||||
const keys = dotted.split(".");
|
const keys = dotted.split(".");
|
||||||
let current = obj;
|
let current = obj;
|
||||||
for (let i = 0; i < keys.length - 1; i++) {
|
for (let i = 0; i < keys.length - 1; i++) {
|
||||||
const key = keys[i];
|
const key = keys[i];
|
||||||
if (!(key in current)) {
|
if (!(key in current)) {
|
||||||
current[key] = {} as Record<string, any>;
|
current[key] = {};
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||||
current = current[key];
|
current = current[key] as Record<string, unknown>;
|
||||||
}
|
}
|
||||||
const lastKey = keys[keys.length - 1];
|
const lastKey = keys[keys.length - 1];
|
||||||
if (lastKey in current) {
|
if (lastKey in current) {
|
||||||
@@ -27,7 +27,7 @@ function redactObject(obj: Record<string, any>, dotted: string, redactedValue =
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
export async function generateReport(settings: ObsidianLiveSyncSettings, core: LiveSyncBaseCore) {
|
export async function generateReport(settings: ObsidianLiveSyncSettings, core: LiveSyncBaseCore) {
|
||||||
let responseConfig: Record<string, any> = {};
|
let responseConfig: Record<string, unknown> = {};
|
||||||
const REDACTED = "𝑅𝐸𝐷𝐴𝐶𝑇𝐸𝐷";
|
const REDACTED = "𝑅𝐸𝐷𝐴𝐶𝑇𝐸𝐷";
|
||||||
if (settings.remoteType == REMOTE_COUCHDB) {
|
if (settings.remoteType == REMOTE_COUCHDB) {
|
||||||
try {
|
try {
|
||||||
@@ -42,7 +42,7 @@ export async function generateReport(settings: ObsidianLiveSyncSettings, core: L
|
|||||||
undefined,
|
undefined,
|
||||||
customHeaders
|
customHeaders
|
||||||
);
|
);
|
||||||
responseConfig = r.json as Record<string, any>;
|
responseConfig = r.json as Record<string, unknown>;
|
||||||
redactObject(responseConfig, "couch_httpd_auth.secret");
|
redactObject(responseConfig, "couch_httpd_auth.secret");
|
||||||
redactObject(responseConfig, "couch_httpd_auth.authentication_db");
|
redactObject(responseConfig, "couch_httpd_auth.authentication_db");
|
||||||
redactObject(responseConfig, "couch_httpd_auth.authentication_redirect");
|
redactObject(responseConfig, "couch_httpd_auth.authentication_redirect");
|
||||||
|
|||||||
+13
-13
@@ -72,7 +72,7 @@ import {
|
|||||||
} from "@lib/common/typeUtils.ts";
|
} from "@lib/common/typeUtils.ts";
|
||||||
export { isInternalFile, getPathFromUXFileInfo, getStoragePathFromUXFileInfo, getDatabasePathFromUXFileInfo };
|
export { isInternalFile, getPathFromUXFileInfo, getStoragePathFromUXFileInfo, getDatabasePathFromUXFileInfo };
|
||||||
|
|
||||||
const memos: { [key: string]: any } = {};
|
const memos: { [key: string]: unknown } = {};
|
||||||
export function memoObject<T>(key: string, obj: T): T {
|
export function memoObject<T>(key: string, obj: T): T {
|
||||||
memos[key] = obj;
|
memos[key] = obj;
|
||||||
return memos[key] as T;
|
return memos[key] as T;
|
||||||
@@ -87,7 +87,7 @@ export async function memoIfNotExist<T>(key: string, func: () => T | Promise<T>)
|
|||||||
}
|
}
|
||||||
export function retrieveMemoObject<T>(key: string): T | false {
|
export function retrieveMemoObject<T>(key: string): T | false {
|
||||||
if (key in memos) {
|
if (key in memos) {
|
||||||
return memos[key];
|
return memos[key] as T;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -128,7 +128,7 @@ export const _requestToCouchDBFetch = async (
|
|||||||
username: string,
|
username: string,
|
||||||
password: string,
|
password: string,
|
||||||
path?: string,
|
path?: string,
|
||||||
body?: any,
|
body?: unknown,
|
||||||
method?: string
|
method?: string
|
||||||
) => {
|
) => {
|
||||||
const utf8str = String.fromCharCode.apply(null, [...writeString(`${username}:${password}`)]);
|
const utf8str = String.fromCharCode.apply(null, [...writeString(`${username}:${password}`)]);
|
||||||
@@ -154,7 +154,7 @@ export const _requestToCouchDB = async (
|
|||||||
credentials: CouchDBCredentials,
|
credentials: CouchDBCredentials,
|
||||||
origin: string,
|
origin: string,
|
||||||
path?: string,
|
path?: string,
|
||||||
body?: any,
|
body?: unknown,
|
||||||
method?: string,
|
method?: string,
|
||||||
customHeaders?: Record<string, string>
|
customHeaders?: Record<string, string>
|
||||||
) => {
|
) => {
|
||||||
@@ -263,27 +263,27 @@ export function compareFileFreshness(
|
|||||||
const _cached = new Map<
|
const _cached = new Map<
|
||||||
string,
|
string,
|
||||||
{
|
{
|
||||||
value: any;
|
value: unknown;
|
||||||
context: Map<string, any>;
|
context: Map<string, unknown>;
|
||||||
}
|
}
|
||||||
>();
|
>();
|
||||||
|
|
||||||
export type MemoOption = {
|
export type MemoOption = {
|
||||||
key: string;
|
key: string;
|
||||||
forceUpdate?: boolean;
|
forceUpdate?: boolean;
|
||||||
validator?: (context: Map<string, any>) => boolean;
|
validator?: (context: Map<string, unknown>) => boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function useMemo<T>(
|
export function useMemo<T>(
|
||||||
{ key, forceUpdate, validator }: MemoOption,
|
{ key, forceUpdate, validator }: MemoOption,
|
||||||
updateFunc: (context: Map<string, any>, prev: T) => T
|
updateFunc: (context: Map<string, unknown>, prev: T) => T
|
||||||
): T {
|
): T {
|
||||||
const cached = _cached.get(key);
|
const cached = _cached.get(key);
|
||||||
const context = cached?.context || new Map<string, any>();
|
const context = cached?.context || new Map<string, unknown>();
|
||||||
if (cached && !forceUpdate && (!validator || (validator && !validator(context)))) {
|
if (cached && !forceUpdate && (!validator || (validator && !validator(context)))) {
|
||||||
return cached.value;
|
return cached.value as T;
|
||||||
}
|
}
|
||||||
const value = updateFunc(context, cached?.value);
|
const value = updateFunc(context, cached?.value as T);
|
||||||
if (value !== cached?.value) {
|
if (value !== cached?.value) {
|
||||||
_cached.set(key, { value, context });
|
_cached.set(key, { value, context });
|
||||||
}
|
}
|
||||||
@@ -294,7 +294,7 @@ export function useMemo<T>(
|
|||||||
const _staticObj = new Map<
|
const _staticObj = new Map<
|
||||||
string,
|
string,
|
||||||
{
|
{
|
||||||
value: any;
|
value: unknown;
|
||||||
}
|
}
|
||||||
>();
|
>();
|
||||||
|
|
||||||
@@ -390,7 +390,7 @@ export async function autosaveCache<K, V>(db: KeyValueDatabase, mapKey: string):
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function onlyInNTimes(n: number, proc: (progress: number) => any) {
|
export function onlyInNTimes(n: number, proc: (progress: number) => unknown) {
|
||||||
let counter = 0;
|
let counter = 0;
|
||||||
return function () {
|
return function () {
|
||||||
if (counter++ % n == 0) {
|
if (counter++ % n == 0) {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ export {
|
|||||||
TextComponent,
|
TextComponent,
|
||||||
ToggleComponent,
|
ToggleComponent,
|
||||||
DropdownComponent,
|
DropdownComponent,
|
||||||
|
Component,
|
||||||
} from "obsidian";
|
} from "obsidian";
|
||||||
export type {
|
export type {
|
||||||
DataWriteOptions,
|
DataWriteOptions,
|
||||||
@@ -41,6 +42,8 @@ export type {
|
|||||||
ListedFiles,
|
ListedFiles,
|
||||||
ValueComponent,
|
ValueComponent,
|
||||||
Stat,
|
Stat,
|
||||||
|
Command,
|
||||||
|
ViewCreator,
|
||||||
} from "obsidian";
|
} from "obsidian";
|
||||||
import { normalizePath as normalizePath_ } from "obsidian";
|
import { normalizePath as normalizePath_ } from "obsidian";
|
||||||
const normalizePath = normalizePath_ as <T extends string | FilePath>(from: T) => T;
|
const normalizePath = normalizePath_ as <T extends string | FilePath>(from: T) => T;
|
||||||
|
|||||||
@@ -1101,7 +1101,7 @@ export class ConfigSync extends LiveSyncCommands {
|
|||||||
this._log(`Config ${data.displayName || data.name} has been applied`, LOG_LEVEL_NOTICE);
|
this._log(`Config ${data.displayName || data.name} has been applied`, LOG_LEVEL_NOTICE);
|
||||||
if (data.category == "PLUGIN_DATA" || data.category == "PLUGIN_MAIN") {
|
if (data.category == "PLUGIN_DATA" || data.category == "PLUGIN_MAIN") {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
const manifests = Object.values(this.app.plugins.manifests) as any as PluginManifest[];
|
const manifests = Object.values(this.app.plugins.manifests) as unknown as PluginManifest[];
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
const enabledPlugins = this.app.plugins.enabledPlugins as Set<string>;
|
const enabledPlugins = this.app.plugins.enabledPlugins as Set<string>;
|
||||||
const pluginManifest = manifests.find(
|
const pluginManifest = manifests.find(
|
||||||
|
|||||||
@@ -1225,7 +1225,7 @@ Offline Changed files: ${files.length}`;
|
|||||||
this.queuedNotificationFiles.clear();
|
this.queuedNotificationFiles.clear();
|
||||||
try {
|
try {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
const manifests = Object.values(this.app.plugins.manifests) as any as PluginManifest[];
|
const manifests = Object.values(this.app.plugins.manifests) as unknown as PluginManifest[];
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
const enabledPlugins = this.app.plugins.enabledPlugins as Set<string>;
|
const enabledPlugins = this.app.plugins.enabledPlugins as Set<string>;
|
||||||
const enabledPluginManifests = manifests.filter((e) => enabledPlugins.has(e.id));
|
const enabledPluginManifests = manifests.filter((e) => enabledPlugins.has(e.id));
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
import type ObsidianLiveSyncPlugin from "@/main.ts";
|
import type ObsidianLiveSyncPlugin from "@/main.ts";
|
||||||
import { MARK_DONE } from "@/modules/features/ModuleLog.ts";
|
import { MARK_DONE } from "@/modules/features/ModuleLog.ts";
|
||||||
import type { LiveSyncCore } from "@/main.ts";
|
import type { LiveSyncCore } from "@/main.ts";
|
||||||
import { __$checkInstanceBinding } from "@lib/dev/checks.ts";
|
// import { __$checkInstanceBinding } from "@lib/dev/checks.ts";
|
||||||
import { createInstanceLogFunction } from "@lib/services/lib/logUtils.ts";
|
import { createInstanceLogFunction } from "@lib/services/lib/logUtils.ts";
|
||||||
|
|
||||||
let noticeIndex = 0;
|
let noticeIndex = 0;
|
||||||
@@ -50,7 +50,7 @@ export abstract class LiveSyncCommands {
|
|||||||
this.core = core;
|
this.core = core;
|
||||||
this.onBindFunction(this.core, this.core.services);
|
this.onBindFunction(this.core, this.core.services);
|
||||||
this._log = createInstanceLogFunction(this.constructor.name, this.services.API);
|
this._log = createInstanceLogFunction(this.constructor.name, this.services.API);
|
||||||
__$checkInstanceBinding(this);
|
// __$checkInstanceBinding(this);
|
||||||
}
|
}
|
||||||
abstract onunload(): void;
|
abstract onunload(): void;
|
||||||
abstract onload(): void | Promise<void>;
|
abstract onload(): void | Promise<void>;
|
||||||
@@ -67,24 +67,24 @@ export abstract class LiveSyncCommands {
|
|||||||
|
|
||||||
_log: ReturnType<typeof createInstanceLogFunction>;
|
_log: ReturnType<typeof createInstanceLogFunction>;
|
||||||
|
|
||||||
_verbose = (msg: any, key?: string) => {
|
_verbose = (msg: unknown, key?: string) => {
|
||||||
this._log(msg, LOG_LEVEL_VERBOSE, key);
|
this._log(msg, LOG_LEVEL_VERBOSE, key);
|
||||||
};
|
};
|
||||||
|
|
||||||
_info = (msg: any, key?: string) => {
|
_info = (msg: unknown, key?: string) => {
|
||||||
this._log(msg, LOG_LEVEL_INFO, key);
|
this._log(msg, LOG_LEVEL_INFO, key);
|
||||||
};
|
};
|
||||||
|
|
||||||
_notice = (msg: any, key?: string) => {
|
_notice = (msg: unknown, key?: string) => {
|
||||||
this._log(msg, LOG_LEVEL_NOTICE, key);
|
this._log(msg, LOG_LEVEL_NOTICE, key);
|
||||||
};
|
};
|
||||||
_progress = (prefix: string = "", level: LOG_LEVEL = LOG_LEVEL_NOTICE) => {
|
_progress = (prefix: string = "", level: LOG_LEVEL = LOG_LEVEL_NOTICE) => {
|
||||||
const key = `keepalive-progress-${noticeIndex++}`;
|
const key = `keepalive-progress-${noticeIndex++}`;
|
||||||
return {
|
return {
|
||||||
log: (msg: any) => {
|
log: (msg: string) => {
|
||||||
this._log(prefix + msg, level, key);
|
this._log(prefix + msg, level, key);
|
||||||
},
|
},
|
||||||
once: (msg: any) => {
|
once: (msg: string) => {
|
||||||
this._log(prefix + msg, level);
|
this._log(prefix + msg, level);
|
||||||
},
|
},
|
||||||
done: (msg: string = "Done") => {
|
done: (msg: string = "Done") => {
|
||||||
@@ -93,7 +93,7 @@ export abstract class LiveSyncCommands {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
_debug = (msg: any, key?: string) => {
|
_debug = (msg: unknown, key?: string) => {
|
||||||
this._log(msg, LOG_LEVEL_VERBOSE, key);
|
this._log(msg, LOG_LEVEL_VERBOSE, key);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { arrayToChunkedArray } from "octagonal-wheels/collection";
|
|||||||
import { EVENT_ANALYSE_DB_USAGE, EVENT_REQUEST_PERFORM_GC_V3, eventHub } from "@/common/events";
|
import { EVENT_ANALYSE_DB_USAGE, EVENT_REQUEST_PERFORM_GC_V3, eventHub } from "@/common/events";
|
||||||
import type { LiveSyncCouchDBReplicator } from "@lib/replication/couchdb/LiveSyncReplicator";
|
import type { LiveSyncCouchDBReplicator } from "@lib/replication/couchdb/LiveSyncReplicator";
|
||||||
import { delay } from "@lib/common/utils";
|
import { delay } from "@lib/common/utils";
|
||||||
|
import { isNotFoundError } from "@/lib/src/common/utils.doc";
|
||||||
// import { _requestToCouchDB } from "@/common/utils";
|
// import { _requestToCouchDB } from "@/common/utils";
|
||||||
const DB_KEY_SEQ = "gc-seq";
|
const DB_KEY_SEQ = "gc-seq";
|
||||||
const DB_KEY_CHUNK_SET = "chunk-set";
|
const DB_KEY_CHUNK_SET = "chunk-set";
|
||||||
@@ -394,7 +395,7 @@ Note: **Make sure to synchronise all devices before deletion.**
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if ((ex as any)?.status == 404) {
|
if (isNotFoundError(ex)) {
|
||||||
this._log(`No revisions found for ${doc._id}`, LOG_LEVEL_VERBOSE);
|
this._log(`No revisions found for ${doc._id}`, LOG_LEVEL_VERBOSE);
|
||||||
} else {
|
} else {
|
||||||
this._log(`Error finding revisions for ${doc._id}`);
|
this._log(`Error finding revisions for ${doc._id}`);
|
||||||
@@ -474,14 +475,14 @@ Are you ready to delete unused chunks?`;
|
|||||||
include_docs: true,
|
include_docs: true,
|
||||||
});
|
});
|
||||||
for (const chunk of deleteChunks.rows) {
|
for (const chunk of deleteChunks.rows) {
|
||||||
if ((chunk as any)?.value?.deleted) {
|
if ((chunk as { value?: { deleted?: boolean } })?.value?.deleted) {
|
||||||
chunkSet.delete(chunk.key as DocumentID);
|
chunkSet.delete(chunk.key as DocumentID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const deleteDocs = deleteChunks.rows
|
const deleteDocs = deleteChunks.rows
|
||||||
.filter((e) => "doc" in e)
|
.filter((e) => "doc" in e)
|
||||||
.map((e) => ({
|
.map((e) => ({
|
||||||
...(e as any).doc!,
|
...(e as { doc?: EntryLeaf }).doc!,
|
||||||
_deleted: true,
|
_deleted: true,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -490,7 +491,7 @@ Are you ready to delete unused chunks?`;
|
|||||||
let successCount = 0;
|
let successCount = 0;
|
||||||
let errored = 0;
|
let errored = 0;
|
||||||
for (const batch of deleteChunkBatch) {
|
for (const batch of deleteChunkBatch) {
|
||||||
const results = await this.database.bulkDocs(batch as EntryLeaf[]);
|
const results = await this.database.bulkDocs(batch);
|
||||||
for (const result of results) {
|
for (const result of results) {
|
||||||
if ("ok" in result) {
|
if ("ok" in result) {
|
||||||
chunkSet.delete(result.id as DocumentID);
|
chunkSet.delete(result.id as DocumentID);
|
||||||
@@ -698,7 +699,7 @@ Success: ${successCount}, Errored: ${errored}`;
|
|||||||
sharedChunkCount: 0,
|
sharedChunkCount: 0,
|
||||||
uniqueChunkSize: orphanChunkSize,
|
uniqueChunkSize: orphanChunkSize,
|
||||||
sharedChunkSize: 0,
|
sharedChunkSize: 0,
|
||||||
} as any);
|
} as const);
|
||||||
|
|
||||||
const csvSrc = result.map((e) => {
|
const csvSrc = result.map((e) => {
|
||||||
return [
|
return [
|
||||||
|
|||||||
+1
-1
Submodule src/lib updated: c926417f82...0278343fc6
+2
-2
@@ -4,7 +4,7 @@ setGetLanguage(getLanguage);
|
|||||||
import { LiveSyncCommands } from "./features/LiveSyncCommands.ts";
|
import { LiveSyncCommands } from "./features/LiveSyncCommands.ts";
|
||||||
import { HiddenFileSync } from "./features/HiddenFileSync/CmdHiddenFileSync.ts";
|
import { HiddenFileSync } from "./features/HiddenFileSync/CmdHiddenFileSync.ts";
|
||||||
import { ConfigSync } from "./features/ConfigSync/CmdConfigSync.ts";
|
import { ConfigSync } from "./features/ConfigSync/CmdConfigSync.ts";
|
||||||
import { ModuleDev } from "./modules/extras/ModuleDev.ts";
|
// import { ModuleDev } from "./modules/extras/ModuleDev.ts";
|
||||||
|
|
||||||
import { ModuleInteractiveConflictResolver } from "./modules/features/ModuleInteractiveConflictResolver.ts";
|
import { ModuleInteractiveConflictResolver } from "./modules/features/ModuleInteractiveConflictResolver.ts";
|
||||||
import { ModuleLog } from "./modules/features/ModuleLog.ts";
|
import { ModuleLog } from "./modules/features/ModuleLog.ts";
|
||||||
@@ -153,7 +153,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
new ModuleObsidianDocumentHistory(this, core),
|
new ModuleObsidianDocumentHistory(this, core),
|
||||||
new ModuleInteractiveConflictResolver(this, core),
|
new ModuleInteractiveConflictResolver(this, core),
|
||||||
new ModuleObsidianGlobalHistory(this, core),
|
new ModuleObsidianGlobalHistory(this, core),
|
||||||
new ModuleDev(this, core),
|
// new ModuleDev(this, core),
|
||||||
new SetupManager(core), // this should be moved to core?
|
new SetupManager(core), // this should be moved to core?
|
||||||
new ModuleMigration(core),
|
new ModuleMigration(core),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import { InternalFileToUXFileInfoStub, TFileToUXFileInfoStub } from "@/modules/c
|
|||||||
* Obsidian-specific type guard adapter
|
* Obsidian-specific type guard adapter
|
||||||
*/
|
*/
|
||||||
class ObsidianTypeGuardAdapter implements IStorageEventTypeGuardAdapter<TFile, TFolder> {
|
class ObsidianTypeGuardAdapter implements IStorageEventTypeGuardAdapter<TFile, TFolder> {
|
||||||
isFile(file: any): file is TFile {
|
isFile(file: unknown): file is TFile {
|
||||||
if (file instanceof TFile) {
|
if (file instanceof TFile) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,7 @@ class ObsidianTypeGuardAdapter implements IStorageEventTypeGuardAdapter<TFile, T
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
isFolder(item: any): item is TFolder {
|
isFolder(item: unknown): item is TFolder {
|
||||||
if (item instanceof TFolder) {
|
if (item instanceof TFolder) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,21 +61,21 @@ export abstract class AbstractModule<
|
|||||||
return this.testDone(false);
|
return this.testDone(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _test(key: string, process: () => Promise<any>) {
|
// async _test(key: string, process: () => Promise<any>) {
|
||||||
this._log(`Testing ${key}`, LOG_LEVEL_VERBOSE);
|
// this._log(`Testing ${key}`, LOG_LEVEL_VERBOSE);
|
||||||
try {
|
// try {
|
||||||
const ret = await process();
|
// const ret = await process();
|
||||||
if (ret !== true) {
|
// if (ret !== true) {
|
||||||
this.addTestResult(key, false, ret.toString());
|
// this.addTestResult(key, false, ret.toString());
|
||||||
return this.testFail(`${key} failed: ${ret}`);
|
// return this.testFail(`${key} failed: ${ret}`);
|
||||||
}
|
// }
|
||||||
this.addTestResult(key, true, "");
|
// this.addTestResult(key, true, "");
|
||||||
} catch (ex: any) {
|
// } catch (ex: any) {
|
||||||
this.addTestResult(key, false, "Failed by Exception", ex.toString());
|
// this.addTestResult(key, false, "Failed by Exception", ex.toString());
|
||||||
return this.testFail(`${key} failed: ${ex}`);
|
// return this.testFail(`${key} failed: ${ex}`);
|
||||||
}
|
// }
|
||||||
return this.testDone();
|
// return this.testDone();
|
||||||
}
|
// }
|
||||||
|
|
||||||
isMainReady() {
|
isMainReady() {
|
||||||
return this.services.appLifecycle.isReady();
|
return this.services.appLifecycle.isReady();
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
import { type Prettify } from "@lib/common/types";
|
|
||||||
import type { LiveSyncCore } from "@/main";
|
import type { LiveSyncCore } from "@/main";
|
||||||
import type ObsidianLiveSyncPlugin from "@/main";
|
import type ObsidianLiveSyncPlugin from "@/main";
|
||||||
import { AbstractModule } from "./AbstractModule.ts";
|
import { AbstractModule } from "./AbstractModule.ts";
|
||||||
import type { ChainableExecuteFunction, OverridableFunctionsKeys } from "./ModuleTypes";
|
|
||||||
|
|
||||||
export type IObsidianModuleBase = OverridableFunctionsKeys<ObsidianLiveSyncPlugin>;
|
|
||||||
export type IObsidianModule = Prettify<Partial<IObsidianModuleBase>>;
|
|
||||||
export type ModuleKeys = keyof IObsidianModule;
|
|
||||||
export type ChainableModuleProps = ChainableExecuteFunction<ObsidianLiveSyncPlugin>;
|
|
||||||
|
|
||||||
export abstract class AbstractObsidianModule extends AbstractModule {
|
export abstract class AbstractObsidianModule extends AbstractModule {
|
||||||
get app() {
|
get app() {
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
import type { Prettify } from "@lib/common/types";
|
|
||||||
import type { LiveSyncCore } from "@/main";
|
|
||||||
|
|
||||||
export type OverridableFunctionsKeys<T> = {
|
|
||||||
[K in keyof T as K extends `$${string}` ? K : never]: T[K];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ChainableExecuteFunction<T> = {
|
|
||||||
[K in keyof T as K extends `$${string}`
|
|
||||||
? T[K] extends (...args: any) => ChainableFunctionResult
|
|
||||||
? K
|
|
||||||
: never
|
|
||||||
: never]: T[K];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ICoreModuleBase = OverridableFunctionsKeys<LiveSyncCore>;
|
|
||||||
export type ICoreModule = Prettify<Partial<ICoreModuleBase>>;
|
|
||||||
export type CoreModuleKeys = keyof ICoreModule;
|
|
||||||
|
|
||||||
export type ChainableFunctionResult =
|
|
||||||
| Promise<boolean | undefined | string>
|
|
||||||
| Promise<boolean | undefined>
|
|
||||||
| Promise<boolean>
|
|
||||||
| Promise<void>;
|
|
||||||
export type ChainableFunctionResultOrAll = Promise<boolean | undefined | string | void>;
|
|
||||||
|
|
||||||
type AllExecuteFunction<T> = {
|
|
||||||
[K in keyof T as K extends `$all${string}`
|
|
||||||
? T[K] extends (...args: any[]) => ChainableFunctionResultOrAll
|
|
||||||
? K
|
|
||||||
: never
|
|
||||||
: never]: T[K];
|
|
||||||
};
|
|
||||||
type EveryExecuteFunction<T> = {
|
|
||||||
[K in keyof T as K extends `$every${string}`
|
|
||||||
? T[K] extends (...args: any[]) => ChainableFunctionResult
|
|
||||||
? K
|
|
||||||
: never
|
|
||||||
: never]: T[K];
|
|
||||||
};
|
|
||||||
type AnyExecuteFunction<T> = {
|
|
||||||
[K in keyof T as K extends `$any${string}`
|
|
||||||
? T[K] extends (...args: any[]) => ChainableFunctionResult
|
|
||||||
? K
|
|
||||||
: never
|
|
||||||
: never]: T[K];
|
|
||||||
};
|
|
||||||
type InjectableFunction<T> = {
|
|
||||||
[K in keyof T as K extends `$$${string}` ? (T[K] extends (...args: any[]) => any ? K : never) : never]: T[K];
|
|
||||||
};
|
|
||||||
export type AllExecuteProps = AllExecuteFunction<LiveSyncCore>;
|
|
||||||
export type EveryExecuteProps = EveryExecuteFunction<LiveSyncCore>;
|
|
||||||
export type AnyExecuteProps = AnyExecuteFunction<LiveSyncCore>;
|
|
||||||
|
|
||||||
export type AllInjectableProps = InjectableFunction<LiveSyncCore>;
|
|
||||||
@@ -21,7 +21,7 @@ import { MARK_LOG_NETWORK_ERROR } from "@lib/services/lib/logUtils";
|
|||||||
|
|
||||||
function isOnlineAndCanReplicate(
|
function isOnlineAndCanReplicate(
|
||||||
errorManager: UnresolvedErrorManager,
|
errorManager: UnresolvedErrorManager,
|
||||||
host: NecessaryServices<"API", any>,
|
host: NecessaryServices<"API", never>,
|
||||||
showMessage: boolean
|
showMessage: boolean
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const errorMessage = "Network is offline";
|
const errorMessage = "Network is offline";
|
||||||
@@ -34,7 +34,7 @@ function isOnlineAndCanReplicate(
|
|||||||
}
|
}
|
||||||
async function canReplicateWithPBKDF2(
|
async function canReplicateWithPBKDF2(
|
||||||
errorManager: UnresolvedErrorManager,
|
errorManager: UnresolvedErrorManager,
|
||||||
host: NecessaryServices<"replicator" | "setting", any>,
|
host: NecessaryServices<"replicator" | "setting", never>,
|
||||||
showMessage: boolean
|
showMessage: boolean
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const currentSettings = host.services.setting.currentSettings();
|
const currentSettings = host.services.setting.currentSettings();
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { Semaphore } from "octagonal-wheels/concurrency/semaphore_v2";
|
|||||||
import { serialized } from "octagonal-wheels/concurrency/lock";
|
import { serialized } from "octagonal-wheels/concurrency/lock";
|
||||||
import type { ReactiveSource } from "octagonal-wheels/dataobject/reactive_v2";
|
import type { ReactiveSource } from "octagonal-wheels/dataobject/reactive_v2";
|
||||||
import type { LiveSyncBaseCore } from "@/LiveSyncBaseCore";
|
import type { LiveSyncBaseCore } from "@/LiveSyncBaseCore";
|
||||||
|
import { isNotFoundError } from "@lib/common/utils.doc";
|
||||||
|
|
||||||
const KV_KEY_REPLICATION_RESULT_PROCESSOR_SNAPSHOT = "replicationResultProcessorSnapshot";
|
const KV_KEY_REPLICATION_RESULT_PROCESSOR_SNAPSHOT = "replicationResultProcessorSnapshot";
|
||||||
type ReplicateResultProcessorState = {
|
type ReplicateResultProcessorState = {
|
||||||
@@ -39,7 +40,7 @@ export class ReplicateResultProcessor {
|
|||||||
private log(message: string, level: LOG_LEVEL = LOG_LEVEL_INFO) {
|
private log(message: string, level: LOG_LEVEL = LOG_LEVEL_INFO) {
|
||||||
Logger(`[ReplicateResultProcessor] ${message}`, level);
|
Logger(`[ReplicateResultProcessor] ${message}`, level);
|
||||||
}
|
}
|
||||||
private logError(e: any) {
|
private logError(e: unknown) {
|
||||||
Logger(e, LOG_LEVEL_VERBOSE);
|
Logger(e, LOG_LEVEL_VERBOSE);
|
||||||
}
|
}
|
||||||
private replicator: ModuleReplicator;
|
private replicator: ModuleReplicator;
|
||||||
@@ -466,8 +467,8 @@ export class ReplicateResultProcessor {
|
|||||||
return false; // This means that the document already processed (While no conflict existed).
|
return false; // This means that the document already processed (While no conflict existed).
|
||||||
}
|
}
|
||||||
return true; // This mostly should not happen, but we have to process it just in case.
|
return true; // This mostly should not happen, but we have to process it just in case.
|
||||||
} catch (e: any) {
|
} catch (e) {
|
||||||
if ("status" in e && e.status == 404) {
|
if (isNotFoundError(e)) {
|
||||||
// getRaw failed due to not existing, it may not be happened normally especially on replication.
|
// getRaw failed due to not existing, it may not be happened normally especially on replication.
|
||||||
// If the process caused by some other reason, we **probably** have to process it.
|
// If the process caused by some other reason, we **probably** have to process it.
|
||||||
// Note that this is not a common case.
|
// Note that this is not a common case.
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import type { InjectableServiceHub } from "@lib/services/InjectableServices.ts";
|
|||||||
import type { LiveSyncCore } from "@/main.ts";
|
import type { LiveSyncCore } from "@/main.ts";
|
||||||
import { REMOTE_P2P } from "@lib/common/models/setting.const.ts";
|
import { REMOTE_P2P } from "@lib/common/models/setting.const.ts";
|
||||||
|
|
||||||
function valueToString(value: any) {
|
function valueToString(value: string | number | boolean | object | undefined): string {
|
||||||
if (typeof value === "boolean") {
|
if (typeof value === "boolean") {
|
||||||
return value ? "true" : "false";
|
return value ? "true" : "false";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ButtonComponent } from "@/deps.ts";
|
import { ButtonComponent } from "@/deps.ts";
|
||||||
import { App, FuzzySuggestModal, MarkdownRenderer, Modal, Plugin, Setting } from "@/deps.ts";
|
import { App, FuzzySuggestModal, MarkdownRenderer, Modal, Plugin, Setting, Component } from "@/deps.ts";
|
||||||
import { EVENT_PLUGIN_UNLOADED, eventHub } from "@/common/events.ts";
|
import { EVENT_PLUGIN_UNLOADED, eventHub } from "@/common/events.ts";
|
||||||
import { compatGlobal, type CompatIntervalHandle } from "@lib/common/coreEnvFunctions.ts";
|
import { compatGlobal, type CompatIntervalHandle } from "@lib/common/coreEnvFunctions.ts";
|
||||||
|
|
||||||
@@ -148,6 +148,7 @@ export class MessageBox<T extends readonly string[]> extends AutoClosableModal {
|
|||||||
wideButton: boolean;
|
wideButton: boolean;
|
||||||
|
|
||||||
onSubmit: (result: string | false) => void;
|
onSubmit: (result: string | false) => void;
|
||||||
|
component: Component = new Component();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
plugin: Plugin,
|
plugin: Plugin,
|
||||||
@@ -189,6 +190,7 @@ export class MessageBox<T extends readonly string[]> extends AutoClosableModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override onOpen() {
|
override onOpen() {
|
||||||
|
this.component.load();
|
||||||
const { contentEl } = this;
|
const { contentEl } = this;
|
||||||
this.titleEl.setText(this.title);
|
this.titleEl.setText(this.title);
|
||||||
const div = contentEl.createDiv();
|
const div = contentEl.createDiv();
|
||||||
@@ -196,7 +198,7 @@ export class MessageBox<T extends readonly string[]> extends AutoClosableModal {
|
|||||||
userSelect: "text",
|
userSelect: "text",
|
||||||
webkitUserSelect: "text",
|
webkitUserSelect: "text",
|
||||||
});
|
});
|
||||||
void MarkdownRenderer.render(this.plugin.app, this.contentMd, div, "/", this.plugin);
|
void MarkdownRenderer.render(this.plugin.app, this.contentMd, div, "/", this.component);
|
||||||
const buttonSetting = new Setting(contentEl);
|
const buttonSetting = new Setting(contentEl);
|
||||||
const labelWrapper = contentEl.createDiv();
|
const labelWrapper = contentEl.createDiv();
|
||||||
labelWrapper.addClass("sls-dialogue-note-wrapper");
|
labelWrapper.addClass("sls-dialogue-note-wrapper");
|
||||||
@@ -254,6 +256,7 @@ export class MessageBox<T extends readonly string[]> extends AutoClosableModal {
|
|||||||
|
|
||||||
override onClose() {
|
override onClose() {
|
||||||
super.onClose();
|
super.onClose();
|
||||||
|
this.component.unload();
|
||||||
const { contentEl } = this;
|
const { contentEl } = this;
|
||||||
contentEl.empty();
|
contentEl.empty();
|
||||||
if (this.timer) {
|
if (this.timer) {
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ export class ObsHttpHandler extends FetchHttpHandler {
|
|||||||
contentType = transformedHeaders["content-type"];
|
contentType = transformedHeaders["content-type"];
|
||||||
}
|
}
|
||||||
|
|
||||||
let transformedBody: any = body;
|
let transformedBody = body;
|
||||||
if (ArrayBuffer.isView(body)) {
|
if (ArrayBuffer.isView(body)) {
|
||||||
transformedBody = new Uint8Array(body.buffer).buffer;
|
transformedBody = new Uint8Array(body.buffer).buffer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,10 +36,11 @@ export class ModuleObsidianEvents extends AbstractObsidianModule {
|
|||||||
this.services.appLifecycle.performRestart();
|
this.services.appLifecycle.performRestart();
|
||||||
}
|
}
|
||||||
|
|
||||||
initialCallback: any;
|
initialCallback: (() => void) | undefined = undefined;
|
||||||
|
|
||||||
swapSaveCommand() {
|
swapSaveCommand() {
|
||||||
this._log("Modifying callback of the save command", LOG_LEVEL_VERBOSE);
|
this._log("Modifying callback of the save command", LOG_LEVEL_VERBOSE);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Editor Tweaking
|
||||||
const saveCommandDefinition = (this.app as any).commands?.commands?.["editor:save-file"];
|
const saveCommandDefinition = (this.app as any).commands?.commands?.["editor:save-file"];
|
||||||
const save = saveCommandDefinition?.callback;
|
const save = saveCommandDefinition?.callback;
|
||||||
if (typeof save === "function") {
|
if (typeof save === "function") {
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { delay, fireAndForget } from "octagonal-wheels/promises";
|
import { delay } from "octagonal-wheels/promises";
|
||||||
import { __onMissingTranslation } from "@lib/common/i18n";
|
import { __onMissingTranslation } from "@lib/common/i18n";
|
||||||
import { AbstractObsidianModule } from "@/modules/AbstractObsidianModule.ts";
|
import { AbstractObsidianModule } from "@/modules/AbstractObsidianModule.ts";
|
||||||
import { LOG_LEVEL_VERBOSE } from "octagonal-wheels/common/logger";
|
import { LOG_LEVEL_VERBOSE } from "octagonal-wheels/common/logger";
|
||||||
import { eventHub } from "@/common/events";
|
// import { enableTestFunction } from "./devUtil/testUtils.ts";
|
||||||
import { enableTestFunction } from "./devUtil/testUtils.ts";
|
|
||||||
import { TestPaneView, VIEW_TYPE_TEST } from "./devUtil/TestPaneView.ts";
|
import { TestPaneView, VIEW_TYPE_TEST } from "./devUtil/TestPaneView.ts";
|
||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
import type { FilePathWithPrefix } from "@lib/common/types.ts";
|
import type { FilePathWithPrefix } from "@lib/common/types.ts";
|
||||||
import type { LiveSyncCore } from "@/main.ts";
|
import type { LiveSyncCore } from "@/main.ts";
|
||||||
|
import type { WorkspaceLeaf } from "@/deps.ts";
|
||||||
export class ModuleDev extends AbstractObsidianModule {
|
export class ModuleDev extends AbstractObsidianModule {
|
||||||
_everyOnloadStart(): Promise<boolean> {
|
_everyOnloadStart(): Promise<boolean> {
|
||||||
__onMissingTranslation(() => {});
|
__onMissingTranslation(() => {});
|
||||||
@@ -37,57 +37,7 @@ export class ModuleDev extends AbstractObsidianModule {
|
|||||||
|
|
||||||
private _everyOnloadAfterLoadSettings(): Promise<boolean> {
|
private _everyOnloadAfterLoadSettings(): Promise<boolean> {
|
||||||
if (!this.settings.enableDebugTools) return Promise.resolve(true);
|
if (!this.settings.enableDebugTools) return Promise.resolve(true);
|
||||||
this.onMissingTranslation = this.onMissingTranslation.bind(this);
|
this.registerView(VIEW_TYPE_TEST, (leaf: WorkspaceLeaf) => new TestPaneView(leaf, this.plugin, this));
|
||||||
__onMissingTranslation((key) => {
|
|
||||||
void this.onMissingTranslation(key);
|
|
||||||
});
|
|
||||||
type STUB = {
|
|
||||||
toc: Set<string>;
|
|
||||||
stub: { [key: string]: { [key: string]: Map<string, Record<string, string>> } };
|
|
||||||
};
|
|
||||||
eventHub.onEvent("document-stub-created", (detail: STUB) => {
|
|
||||||
fireAndForget(async () => {
|
|
||||||
const stub = detail.stub;
|
|
||||||
const toc = detail.toc;
|
|
||||||
|
|
||||||
const stubDocX = Object.entries(stub)
|
|
||||||
.map(([key, value]) => {
|
|
||||||
return [
|
|
||||||
`## ${key}`,
|
|
||||||
Object.entries(value)
|
|
||||||
.map(([key2, value2]) => {
|
|
||||||
return [
|
|
||||||
`### ${key2}`,
|
|
||||||
[...value2.entries()].map(([key3, value3]) => {
|
|
||||||
// return `#### ${key3}` + "\n" + JSON.stringify(value3);
|
|
||||||
const isObsolete = value3["is_obsolete"] ? " (obsolete)" : "";
|
|
||||||
const desc = value3["desc"] ?? "";
|
|
||||||
const key = value3["key"] ? "Setting key: " + value3["key"] + "\n" : "";
|
|
||||||
return `#### ${key3}${isObsolete}\n${key}${desc}\n`;
|
|
||||||
}),
|
|
||||||
].flat();
|
|
||||||
})
|
|
||||||
.flat(),
|
|
||||||
].flat();
|
|
||||||
})
|
|
||||||
.flat();
|
|
||||||
const stubDocMD =
|
|
||||||
`
|
|
||||||
| Icon | Description |
|
|
||||||
| :---: | ----------------------------------------------------------------- |
|
|
||||||
` +
|
|
||||||
[...toc.values()].map((e) => `${e}`).join("\n") +
|
|
||||||
"\n\n" +
|
|
||||||
stubDocX.join("\n");
|
|
||||||
await this.core.storageAccess.writeHiddenFileAuto(
|
|
||||||
this.app.vault.configDir + "/ls-debug/stub-doc.md",
|
|
||||||
stubDocMD
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
enableTestFunction(this.plugin);
|
|
||||||
this.registerView(VIEW_TYPE_TEST, (leaf) => new TestPaneView(leaf, this.plugin, this));
|
|
||||||
this.addCommand({
|
this.addCommand({
|
||||||
id: "view-test",
|
id: "view-test",
|
||||||
name: "Open Test dialogue",
|
name: "Open Test dialogue",
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
import { fireAndForget } from "@lib/common/utils.ts";
|
|
||||||
import { serialized } from "octagonal-wheels/concurrency/lock";
|
|
||||||
import type ObsidianLiveSyncPlugin from "@/main.ts";
|
|
||||||
|
|
||||||
let plugin: ObsidianLiveSyncPlugin;
|
|
||||||
export function enableTestFunction(plugin_: ObsidianLiveSyncPlugin) {
|
|
||||||
plugin = plugin_;
|
|
||||||
}
|
|
||||||
export function addDebugFileLog(message: any, stackLog = false) {
|
|
||||||
fireAndForget(
|
|
||||||
serialized("debug-log", async () => {
|
|
||||||
const now = new Date();
|
|
||||||
const filename = `debug-log`;
|
|
||||||
const time = now.toISOString().split("T")[0];
|
|
||||||
const outFile = `${filename}${time}.jsonl`;
|
|
||||||
// const messageContent = typeof message == "string" ? message : message instanceof Error ? `${message.name}:${message.message}` : JSON.stringify(message, null, 2);
|
|
||||||
const timestamp = now.toLocaleString();
|
|
||||||
const timestampEpoch = now;
|
|
||||||
let out = { timestamp: timestamp, epoch: timestampEpoch } as Record<string, any>;
|
|
||||||
if (message instanceof Error) {
|
|
||||||
// debugger;
|
|
||||||
// console.dir(message.stack);
|
|
||||||
out = { ...out, message };
|
|
||||||
} else if (stackLog) {
|
|
||||||
if (stackLog) {
|
|
||||||
const stackE = new Error();
|
|
||||||
const stack = stackE.stack;
|
|
||||||
out = { ...out, stack };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (typeof message == "object") {
|
|
||||||
out = { ...out, ...message };
|
|
||||||
} else {
|
|
||||||
out = {
|
|
||||||
result: message,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// const out = "--" + timestamp + "--\n" + messageContent + " " + (stack || "");
|
|
||||||
// const out
|
|
||||||
try {
|
|
||||||
await plugin.core.storageAccess.appendHiddenFile(
|
|
||||||
plugin.core.services.API.getSystemConfigDir() + "/ls-debug/" + outFile,
|
|
||||||
JSON.stringify(out) + "\n"
|
|
||||||
);
|
|
||||||
} catch {
|
|
||||||
//NO OP
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -139,7 +139,7 @@ export class DocumentHistoryModal extends Modal {
|
|||||||
this.range.value = `${this.revs_info.length - 1 - rIndex}`;
|
this.range.value = `${this.revs_info.length - 1 - rIndex}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const index = this.revs_info.length - 1 - (this.range.value as any) / 1;
|
const index = this.revs_info.length - 1 - (Number(this.range.value) || 0);
|
||||||
const rev = this.revs_info[index];
|
const rev = this.revs_info[index];
|
||||||
await this.showExactRev(rev.rev);
|
await this.showExactRev(rev.rev);
|
||||||
}
|
}
|
||||||
@@ -251,7 +251,7 @@ export class DocumentHistoryModal extends Modal {
|
|||||||
}
|
}
|
||||||
let rendered = false;
|
let rendered = false;
|
||||||
if (this.showDiff) {
|
if (this.showDiff) {
|
||||||
const prevRevIdx = this.revs_info.length - 1 - ((this.range.value as any) / 1 - 1);
|
const prevRevIdx = this.revs_info.length - 1 - ((Number(this.range.value) || 0) - 1);
|
||||||
if (prevRevIdx >= 0 && prevRevIdx < this.revs_info.length) {
|
if (prevRevIdx >= 0 && prevRevIdx < this.revs_info.length) {
|
||||||
const oldRev = this.revs_info[prevRevIdx].rev;
|
const oldRev = this.revs_info[prevRevIdx].rev;
|
||||||
const w2 = await db.getDBEntry(this.file, { rev: oldRev }, false, false, true);
|
const w2 = await db.getDBEntry(this.file, { rev: oldRev }, false, false, true);
|
||||||
@@ -550,7 +550,7 @@ export class DocumentHistoryModal extends Modal {
|
|||||||
if (this.showDiff) {
|
if (this.showDiff) {
|
||||||
checkbox.checked = true;
|
checkbox.checked = true;
|
||||||
}
|
}
|
||||||
checkbox.addEventListener("input", (evt: any) => {
|
checkbox.addEventListener("input", (evt: Event) => {
|
||||||
this.showDiff = checkbox.checked;
|
this.showDiff = checkbox.checked;
|
||||||
this.app.saveLocalStorage("ols-history-highlightdiff", this.showDiff == true ? "1" : null);
|
this.app.saveLocalStorage("ols-history-highlightdiff", this.showDiff == true ? "1" : null);
|
||||||
this.updateDiffNavVisibility();
|
this.updateDiffNavVisibility();
|
||||||
@@ -565,7 +565,7 @@ export class DocumentHistoryModal extends Modal {
|
|||||||
if (this.diffOnly) {
|
if (this.diffOnly) {
|
||||||
checkbox.checked = true;
|
checkbox.checked = true;
|
||||||
}
|
}
|
||||||
checkbox.addEventListener("input", (evt: any) => {
|
checkbox.addEventListener("input", (evt: Event) => {
|
||||||
this.diffOnly = checkbox.checked;
|
this.diffOnly = checkbox.checked;
|
||||||
this.app.saveLocalStorage("ols-history-diffonly", this.diffOnly == true ? "1" : null);
|
this.app.saveLocalStorage("ols-history-diffonly", this.diffOnly == true ? "1" : null);
|
||||||
void scheduleOnceIfDuplicated("loadRevs", () => this.loadRevs());
|
void scheduleOnceIfDuplicated("loadRevs", () => this.loadRevs());
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { AbstractObsidianModule } from "@/modules/AbstractObsidianModule.ts";
|
import { AbstractObsidianModule } from "@/modules/AbstractObsidianModule.ts";
|
||||||
import { VIEW_TYPE_GLOBAL_HISTORY, GlobalHistoryView } from "./GlobalHistory/GlobalHistoryView.ts";
|
import { VIEW_TYPE_GLOBAL_HISTORY, GlobalHistoryView } from "./GlobalHistory/GlobalHistoryView.ts";
|
||||||
|
import type { WorkspaceLeaf } from "@/deps.ts";
|
||||||
|
|
||||||
export class ModuleObsidianGlobalHistory extends AbstractObsidianModule {
|
export class ModuleObsidianGlobalHistory extends AbstractObsidianModule {
|
||||||
_everyOnloadStart(): Promise<boolean> {
|
_everyOnloadStart(): Promise<boolean> {
|
||||||
@@ -11,7 +12,7 @@ export class ModuleObsidianGlobalHistory extends AbstractObsidianModule {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.registerView(VIEW_TYPE_GLOBAL_HISTORY, (leaf) => new GlobalHistoryView(leaf, this.plugin));
|
this.registerView(VIEW_TYPE_GLOBAL_HISTORY, (leaf: WorkspaceLeaf) => new GlobalHistoryView(leaf, this.plugin));
|
||||||
|
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ import { generateReport } from "@/common/reportTool.ts";
|
|||||||
|
|
||||||
// DI the log again.
|
// DI the log again.
|
||||||
const recentLogEntries = reactiveSource<LogEntry[]>([]);
|
const recentLogEntries = reactiveSource<LogEntry[]>([]);
|
||||||
const globalLogFunction = (message: any, level?: number, key?: string) => {
|
const globalLogFunction = (message: unknown, level?: number, key?: string) => {
|
||||||
const messageX =
|
const messageX =
|
||||||
message instanceof Error
|
message instanceof Error
|
||||||
? new LiveSyncError("[Error Logged]: " + message.message, { cause: message })
|
? new LiveSyncError("[Error Logged]: " + message.message, { cause: message })
|
||||||
@@ -501,7 +501,7 @@ ${stringifyYaml(info)}
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
__addLog(message: any, level: LOG_LEVEL = LOG_LEVEL_INFO, key = ""): void {
|
__addLog(message: unknown, level: LOG_LEVEL = LOG_LEVEL_INFO, key = ""): void {
|
||||||
if (level == LOG_LEVEL_DEBUG && !showDebugLog) {
|
if (level == LOG_LEVEL_DEBUG && !showDebugLog) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
} from "@/deps.ts";
|
} from "@/deps.ts";
|
||||||
import { unique } from "octagonal-wheels/collection";
|
import { unique } from "octagonal-wheels/collection";
|
||||||
import { LEVEL_ADVANCED, LEVEL_POWER_USER, statusDisplay, type ConfigurationItem } from "@lib/common/types.ts";
|
import { LEVEL_ADVANCED, LEVEL_POWER_USER, statusDisplay, type ConfigurationItem } from "@lib/common/types.ts";
|
||||||
import { createStub, type ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
import { type ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
||||||
import {
|
import {
|
||||||
type AllSettingItemKey,
|
type AllSettingItemKey,
|
||||||
getConfig,
|
getConfig,
|
||||||
@@ -19,7 +19,7 @@ import {
|
|||||||
type AllBooleanItemKey,
|
type AllBooleanItemKey,
|
||||||
} from "./settingConstants.ts";
|
} from "./settingConstants.ts";
|
||||||
import { $msg } from "@lib/common/i18n.ts";
|
import { $msg } from "@lib/common/i18n.ts";
|
||||||
import { findAttrFromParent, wrapMemo, type AutoWireOption, type OnUpdateResult } from "./SettingPane.ts";
|
import { wrapMemo, type AutoWireOption, type OnUpdateResult } from "./SettingPane.ts";
|
||||||
|
|
||||||
export class LiveSyncSetting extends Setting {
|
export class LiveSyncSetting extends Setting {
|
||||||
autoWiredComponent?: TextComponent | ToggleComponent | DropdownComponent | ButtonComponent | TextAreaComponent;
|
autoWiredComponent?: TextComponent | ToggleComponent | DropdownComponent | ButtonComponent | TextAreaComponent;
|
||||||
@@ -35,37 +35,19 @@ export class LiveSyncSetting extends Setting {
|
|||||||
hasPassword: boolean = false;
|
hasPassword: boolean = false;
|
||||||
|
|
||||||
invalidateValue?: () => void;
|
invalidateValue?: () => void;
|
||||||
setValue?: (value: any) => void;
|
setValue?: (value: unknown) => void;
|
||||||
constructor(containerEl: HTMLElement) {
|
constructor(containerEl: HTMLElement) {
|
||||||
super(containerEl);
|
super(containerEl);
|
||||||
LiveSyncSetting.env.settingComponents.push(this);
|
LiveSyncSetting.env.settingComponents.push(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
_createDocStub(key: string, value: string | DocumentFragment) {
|
|
||||||
DEV: {
|
|
||||||
const paneName = findAttrFromParent(this.settingEl, "data-pane");
|
|
||||||
const panelName = findAttrFromParent(this.settingEl, "data-panel");
|
|
||||||
const itemName =
|
|
||||||
typeof this.nameBuf == "string" ? this.nameBuf : (this.nameBuf.textContent?.toString() ?? "");
|
|
||||||
const strValue = typeof value == "string" ? value : (value.textContent?.toString() ?? "");
|
|
||||||
|
|
||||||
createStub(itemName, key, strValue, panelName, paneName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override setDesc(desc: string | DocumentFragment): this {
|
override setDesc(desc: string | DocumentFragment): this {
|
||||||
this.descBuf = desc;
|
this.descBuf = desc;
|
||||||
DEV: {
|
|
||||||
this._createDocStub("desc", desc);
|
|
||||||
}
|
|
||||||
super.setDesc(desc);
|
super.setDesc(desc);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
override setName(name: string | DocumentFragment): this {
|
override setName(name: string | DocumentFragment): this {
|
||||||
this.nameBuf = name;
|
this.nameBuf = name;
|
||||||
DEV: {
|
|
||||||
this._createDocStub("name", name);
|
|
||||||
}
|
|
||||||
super.setName(name);
|
super.setName(name);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -84,11 +66,6 @@ export class LiveSyncSetting extends Setting {
|
|||||||
if (conf.desc) {
|
if (conf.desc) {
|
||||||
this.setDesc(conf.desc);
|
this.setDesc(conf.desc);
|
||||||
}
|
}
|
||||||
DEV: {
|
|
||||||
this._createDocStub("key", key);
|
|
||||||
if (conf.obsolete) this._createDocStub("is_obsolete", "true");
|
|
||||||
if (conf.level) this._createDocStub("level", conf.level);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.holdValue = opt?.holdValue || this.holdValue;
|
this.holdValue = opt?.holdValue || this.holdValue;
|
||||||
this.selfKey = key;
|
this.selfKey = key;
|
||||||
@@ -102,7 +79,7 @@ export class LiveSyncSetting extends Setting {
|
|||||||
}
|
}
|
||||||
return conf;
|
return conf;
|
||||||
}
|
}
|
||||||
autoWireComponent(component: ValueComponent<any>, conf?: ConfigurationItem, opt?: AutoWireOption) {
|
autoWireComponent<T>(component: ValueComponent<T>, conf?: ConfigurationItem, opt?: AutoWireOption) {
|
||||||
this.placeHolderBuf = conf?.placeHolder || opt?.placeHolder || "";
|
this.placeHolderBuf = conf?.placeHolder || opt?.placeHolder || "";
|
||||||
if (conf?.level == LEVEL_ADVANCED) {
|
if (conf?.level == LEVEL_ADVANCED) {
|
||||||
this.settingEl.toggleClass("sls-setting-advanced", true);
|
this.settingEl.toggleClass("sls-setting-advanced", true);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { App, PluginSettingTab } from "@/deps.ts";
|
import { App, Component, PluginSettingTab } from "@/deps.ts";
|
||||||
import {
|
import {
|
||||||
type ObsidianLiveSyncSettings,
|
type ObsidianLiveSyncSettings,
|
||||||
type RemoteDBSettings,
|
type RemoteDBSettings,
|
||||||
@@ -40,12 +40,13 @@ import { JournalSyncMinio } from "@lib/replication/journal/objectstore/JournalSy
|
|||||||
import { paneChangeLog } from "./PaneChangeLog.ts";
|
import { paneChangeLog } from "./PaneChangeLog.ts";
|
||||||
import {
|
import {
|
||||||
enableOnly,
|
enableOnly,
|
||||||
findAttrFromParent,
|
// findAttrFromParent,
|
||||||
getLevelStr,
|
// getLevelStr,
|
||||||
setLevelClass,
|
setLevelClass,
|
||||||
setStyle,
|
setStyle,
|
||||||
visibleOnly,
|
visibleOnly,
|
||||||
type OnSavedHandler,
|
type OnSavedHandler,
|
||||||
|
type OnSavedHandlerFunc,
|
||||||
type OnUpdateFunc,
|
type OnUpdateFunc,
|
||||||
type OnUpdateResult,
|
type OnUpdateResult,
|
||||||
type PageFunctions,
|
type PageFunctions,
|
||||||
@@ -65,28 +66,14 @@ import { paneMaintenance } from "./PaneMaintenance.ts";
|
|||||||
import { compatGlobal } from "@lib/common/coreEnvFunctions.ts";
|
import { compatGlobal } from "@lib/common/coreEnvFunctions.ts";
|
||||||
|
|
||||||
// For creating a document
|
// For creating a document
|
||||||
const toc = new Set<string>();
|
// const toc = new Set<string>();
|
||||||
const stubs = {} as {
|
|
||||||
[key: string]: { [key: string]: Map<string, Record<string, string>> };
|
|
||||||
};
|
|
||||||
export function createStub(name: string, key: string, value: string, panel: string, pane: string) {
|
|
||||||
DEV: {
|
|
||||||
if (!(pane in stubs)) {
|
|
||||||
stubs[pane] = {};
|
|
||||||
}
|
|
||||||
if (!(panel in stubs[pane])) {
|
|
||||||
stubs[pane][panel] = new Map<string, Record<string, string>>();
|
|
||||||
}
|
|
||||||
const old = stubs[pane][panel].get(name) ?? {};
|
|
||||||
stubs[pane][panel].set(name, { ...old, [key]: value });
|
|
||||||
scheduleTask("update-stub", 100, () => {
|
|
||||||
eventHub.emitEvent("document-stub-created", { toc: toc, stub: stubs });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
||||||
plugin: ObsidianLiveSyncPlugin;
|
plugin: ObsidianLiveSyncPlugin;
|
||||||
|
private _lifetimeComponent: Component = new Component();
|
||||||
|
get lifetimeComponent(): Component {
|
||||||
|
return this._lifetimeComponent;
|
||||||
|
}
|
||||||
get core() {
|
get core() {
|
||||||
return this.plugin.core;
|
return this.plugin.core;
|
||||||
}
|
}
|
||||||
@@ -181,7 +168,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
// if (runOnSaved) {
|
// if (runOnSaved) {
|
||||||
const handlers = this.onSavedHandlers
|
const handlers = this.onSavedHandlers
|
||||||
.filter((e) => appliedKeys.indexOf(e.key) !== -1)
|
.filter((e) => appliedKeys.indexOf(e.key) !== -1)
|
||||||
.map((e) => Promise.resolve(e.handler(this.editingSettings[e.key as AllSettingItemKey])));
|
.map((e) => Promise.resolve(e.handler(this.editingSettings[e.key])));
|
||||||
await Promise.all(handlers);
|
await Promise.all(handlers);
|
||||||
// }
|
// }
|
||||||
keys.forEach((e) => this.refreshSetting(e));
|
keys.forEach((e) => this.refreshSetting(e));
|
||||||
@@ -287,7 +274,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
// UI Element Wrapper -->
|
// UI Element Wrapper -->
|
||||||
settingComponents = [] as Setting[];
|
settingComponents = [] as Setting[];
|
||||||
controlledElementFunc = [] as UpdateFunction[];
|
controlledElementFunc = [] as UpdateFunction[];
|
||||||
onSavedHandlers = [] as OnSavedHandler<any>[];
|
onSavedHandlers = [] as OnSavedHandler<AllSettingItemKey>[];
|
||||||
|
|
||||||
inWizard: boolean = false;
|
inWizard: boolean = false;
|
||||||
|
|
||||||
@@ -370,8 +357,9 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
return Promise.resolve(elm);
|
return Promise.resolve(elm);
|
||||||
}
|
}
|
||||||
|
|
||||||
addOnSaved<T extends AllSettingItemKey>(key: T, func: (value: AllSettings[T]) => Promise<void> | void) {
|
addOnSaved<T extends AllSettingItemKey>(key: T, func: OnSavedHandlerFunc<T>) {
|
||||||
this.onSavedHandlers.push({ key, handler: func });
|
const newHandler = { key, handler: func } as OnSavedHandler<AllSettingItemKey>;
|
||||||
|
this.onSavedHandlers.push(newHandler);
|
||||||
}
|
}
|
||||||
resetEditingSettings() {
|
resetEditingSettings() {
|
||||||
this._editingSettings = undefined;
|
this._editingSettings = undefined;
|
||||||
@@ -379,6 +367,9 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override hide() {
|
override hide() {
|
||||||
|
super.hide();
|
||||||
|
this._lifetimeComponent?.unload();
|
||||||
|
this._lifetimeComponent = undefined;
|
||||||
this.isShown = false;
|
this.isShown = false;
|
||||||
}
|
}
|
||||||
isShown: boolean = false;
|
isShown: boolean = false;
|
||||||
@@ -663,8 +654,10 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
display(): void {
|
override display(): void {
|
||||||
const changeDisplay = this.changeDisplay.bind(this);
|
const changeDisplay = this.changeDisplay.bind(this);
|
||||||
|
// Make sure lifetime component is loaded for markdown rendering in panes.
|
||||||
|
this._lifetimeComponent.load();
|
||||||
const { containerEl } = this;
|
const { containerEl } = this;
|
||||||
this.settingComponents.length = 0;
|
this.settingComponents.length = 0;
|
||||||
this.controlledElementFunc.length = 0;
|
this.controlledElementFunc.length = 0;
|
||||||
@@ -718,7 +711,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
visibleOnly(() => this.isNeedRebuildLocal() || this.isNeedRebuildRemote())
|
visibleOnly(() => this.isNeedRebuildLocal() || this.isNeedRebuildRemote())
|
||||||
);
|
);
|
||||||
|
|
||||||
let paneNo = 0;
|
// let paneNo = 0;
|
||||||
const addPane = (
|
const addPane = (
|
||||||
parentEl: HTMLElement,
|
parentEl: HTMLElement,
|
||||||
title: string,
|
title: string,
|
||||||
@@ -728,20 +721,9 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
level?: ConfigLevel
|
level?: ConfigLevel
|
||||||
) => {
|
) => {
|
||||||
const el = this.createEl(parentEl, "div", { text: "" });
|
const el = this.createEl(parentEl, "div", { text: "" });
|
||||||
DEV: {
|
|
||||||
const mdTitle = `${paneNo++}. ${title}${getLevelStr(level ?? "")}`;
|
|
||||||
el.setAttribute("data-pane", mdTitle);
|
|
||||||
toc.add(
|
|
||||||
`| ${icon} | [${mdTitle}](#${mdTitle
|
|
||||||
.toLowerCase()
|
|
||||||
.replace(/ /g, "-")
|
|
||||||
.replace(/[^\w\s-]/g, "")}) | `
|
|
||||||
);
|
|
||||||
}
|
|
||||||
setLevelClass(el, level);
|
setLevelClass(el, level);
|
||||||
// TODO: Refactor to use Obsidian's recommended way to create heading.
|
new Setting(el).setName(title).setHeading().setClass("sls-setting-pane-title");
|
||||||
// eslint-disable-next-line obsidianmd/settings-tab/no-manual-html-headings
|
|
||||||
el.createEl("h3", { text: title, cls: "sls-setting-pane-title" });
|
|
||||||
if (this.menuEl) {
|
if (this.menuEl) {
|
||||||
this.menuEl.createEl(
|
this.menuEl.createEl(
|
||||||
"label",
|
"label",
|
||||||
@@ -772,7 +754,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
// });
|
// });
|
||||||
return p;
|
return p;
|
||||||
};
|
};
|
||||||
const panelNoMap = {} as { [key: string]: number };
|
// const panelNoMap = {} as { [key: string]: number };
|
||||||
const addPanel = (
|
const addPanel = (
|
||||||
parentEl: HTMLElement,
|
parentEl: HTMLElement,
|
||||||
title: string,
|
title: string,
|
||||||
@@ -781,15 +763,6 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
level?: ConfigLevel
|
level?: ConfigLevel
|
||||||
) => {
|
) => {
|
||||||
const el = this.createEl(parentEl, "div", { text: "" }, callback, func);
|
const el = this.createEl(parentEl, "div", { text: "" }, callback, func);
|
||||||
DEV: {
|
|
||||||
const paneNo = findAttrFromParent(parentEl, "data-pane");
|
|
||||||
if (!(paneNo in panelNoMap)) {
|
|
||||||
panelNoMap[paneNo] = 0;
|
|
||||||
}
|
|
||||||
panelNoMap[paneNo] += 1;
|
|
||||||
const panelNo = panelNoMap[paneNo];
|
|
||||||
el.setAttribute("data-panel", `${panelNo}. ${title}${getLevelStr(level ?? "")}`);
|
|
||||||
}
|
|
||||||
setLevelClass(el, level);
|
setLevelClass(el, level);
|
||||||
this.createEl(el, "h4", { text: title, cls: "sls-setting-panel-title" });
|
this.createEl(el, "h4", { text: title, cls: "sls-setting-panel-title" });
|
||||||
const p = Promise.resolve(el);
|
const p = Promise.resolve(el);
|
||||||
@@ -823,6 +796,9 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
return callback;
|
return callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Add panes
|
||||||
|
|
||||||
|
// TODO: Refactor to new API style.
|
||||||
void addPane(containerEl, $msg("obsidianLiveSyncSettingTab.panelChangeLog"), "💬", 100, false).then(
|
void addPane(containerEl, $msg("obsidianLiveSyncSettingTab.panelChangeLog"), "💬", 100, false).then(
|
||||||
bindPane(paneChangeLog)
|
bindPane(paneChangeLog)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ export function paneChangeLog(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElem
|
|||||||
undefined,
|
undefined,
|
||||||
visibleOnly(() => !this.isConfiguredAs("versionUpFlash", ""))
|
visibleOnly(() => !this.isConfiguredAs("versionUpFlash", ""))
|
||||||
);
|
);
|
||||||
|
|
||||||
this.createEl(
|
this.createEl(
|
||||||
cx,
|
cx,
|
||||||
"div",
|
"div",
|
||||||
@@ -58,6 +57,6 @@ export function paneChangeLog(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElem
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
fireAndForget(() =>
|
fireAndForget(() =>
|
||||||
MarkdownRenderer.render(this.plugin.app, updateInformation, informationDivEl, "/", this.plugin)
|
MarkdownRenderer.render(this.plugin.app, updateInformation, informationDivEl, "/", this.lifetimeComponent)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
type LoadedEntry,
|
type LoadedEntry,
|
||||||
type MetaEntry,
|
type MetaEntry,
|
||||||
type FilePath,
|
type FilePath,
|
||||||
|
type EntryDoc,
|
||||||
} from "@lib/common/types.ts";
|
} from "@lib/common/types.ts";
|
||||||
import { createBlob, getFileRegExp, isDocContentSame, readAsBlob } from "@lib/common/utils.ts";
|
import { createBlob, getFileRegExp, isDocContentSame, readAsBlob } from "@lib/common/utils.ts";
|
||||||
import { Logger } from "@lib/common/logger.ts";
|
import { Logger } from "@lib/common/logger.ts";
|
||||||
@@ -441,8 +442,8 @@ export function paneHatch(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement,
|
|||||||
const newData = entriesToDelete.rows.map((e) => ({
|
const newData = entriesToDelete.rows.map((e) => ({
|
||||||
...e.doc,
|
...e.doc,
|
||||||
_deleted: true,
|
_deleted: true,
|
||||||
}));
|
})) as EntryDoc[];
|
||||||
const r = await this.core.localDatabase.bulkDocsRaw(newData as any[]);
|
const r = await this.core.localDatabase.bulkDocsRaw(newData);
|
||||||
// Do not care about the result.
|
// Do not care about the result.
|
||||||
Logger(
|
Logger(
|
||||||
`${r.length} items have been removed, to confirm how many items are left, please perform it again.`,
|
`${r.length} items have been removed, to confirm how many items are left, please perform it again.`,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
type ObsidianLiveSyncSettings,
|
type ObsidianLiveSyncSettings,
|
||||||
LOG_LEVEL_VERBOSE,
|
LOG_LEVEL_VERBOSE,
|
||||||
} from "@lib/common/types.ts";
|
} from "@lib/common/types.ts";
|
||||||
import { Menu } from "@/deps.ts";
|
import { Menu, type ButtonComponent } from "@/deps.ts";
|
||||||
import { $msg } from "@lib/common/i18n.ts";
|
import { $msg } from "@lib/common/i18n.ts";
|
||||||
import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts";
|
import { LiveSyncSetting as Setting } from "./LiveSyncSetting.ts";
|
||||||
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
import type { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab.ts";
|
||||||
@@ -37,9 +37,9 @@ import { syncActivatedRemoteSettings } from "./remoteConfigBuffer.ts";
|
|||||||
|
|
||||||
function getSettingsFromEditingSettings(editingSettings: AllSettings): ObsidianLiveSyncSettings {
|
function getSettingsFromEditingSettings(editingSettings: AllSettings): ObsidianLiveSyncSettings {
|
||||||
const workObj = { ...editingSettings } as ObsidianLiveSyncSettings;
|
const workObj = { ...editingSettings } as ObsidianLiveSyncSettings;
|
||||||
const keys = Object.keys(OnDialogSettingsDefault);
|
const keys = Object.keys(OnDialogSettingsDefault) as (keyof ObsidianLiveSyncSettings)[];
|
||||||
for (const k of keys) {
|
for (const k of keys) {
|
||||||
delete (workObj as any)[k];
|
delete workObj[k];
|
||||||
}
|
}
|
||||||
return workObj;
|
return workObj;
|
||||||
}
|
}
|
||||||
@@ -72,7 +72,7 @@ function serializeRemoteConfiguration(settings: ObsidianLiveSyncSettings): strin
|
|||||||
return ConnectionStringParser.serialize({ type: "couchdb", settings });
|
return ConnectionStringParser.serialize({ type: "couchdb", settings });
|
||||||
}
|
}
|
||||||
|
|
||||||
function setEmojiButton(button: any, emoji: string, tooltip: string) {
|
function setEmojiButton(button: ButtonComponent, emoji: string, tooltip: string) {
|
||||||
button.setButtonText(emoji);
|
button.setButtonText(emoji);
|
||||||
button.setTooltip(tooltip, { delay: 10, placement: "top" });
|
button.setTooltip(tooltip, { delay: 10, placement: "top" });
|
||||||
// button.buttonEl.addClass("clickable-icon");
|
// button.buttonEl.addClass("clickable-icon");
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { visibleOnly } from "./SettingPane.ts";
|
|||||||
import { DEFAULT_SETTINGS } from "@lib/common/types.ts";
|
import { DEFAULT_SETTINGS } from "@lib/common/types.ts";
|
||||||
import { request } from "@/deps.ts";
|
import { request } from "@/deps.ts";
|
||||||
import { SetupManager, UserMode } from "@/modules/features/SetupManager.ts";
|
import { SetupManager, UserMode } from "@/modules/features/SetupManager.ts";
|
||||||
|
import { LiveSyncError } from "@/lib/src/common/LSError.ts";
|
||||||
export function paneSetup(
|
export function paneSetup(
|
||||||
this: ObsidianLiveSyncSettingTab,
|
this: ObsidianLiveSyncSettingTab,
|
||||||
paneEl: HTMLElement,
|
paneEl: HTMLElement,
|
||||||
@@ -145,8 +146,9 @@ export function paneSetup(
|
|||||||
let remoteTroubleShootMDSrc = "";
|
let remoteTroubleShootMDSrc = "";
|
||||||
try {
|
try {
|
||||||
remoteTroubleShootMDSrc = await request(`${rawRepoURI}${basePath}/${filename}`);
|
remoteTroubleShootMDSrc = await request(`${rawRepoURI}${basePath}/${filename}`);
|
||||||
} catch (ex: any) {
|
} catch (ex) {
|
||||||
remoteTroubleShootMDSrc = `${$msg("obsidianLiveSyncSettingTab.logErrorOccurred")}\n${ex.toString()}`;
|
const err = LiveSyncError.fromError(ex);
|
||||||
|
remoteTroubleShootMDSrc = `${$msg("obsidianLiveSyncSettingTab.logErrorOccurred")}\n${err.toString()}`;
|
||||||
}
|
}
|
||||||
const remoteTroubleShootMD = remoteTroubleShootMDSrc.replace(
|
const remoteTroubleShootMD = remoteTroubleShootMDSrc.replace(
|
||||||
/\((.*?(.png)|(.jpg))\)/g,
|
/\((.*?(.png)|(.jpg))\)/g,
|
||||||
@@ -158,7 +160,7 @@ export function paneSetup(
|
|||||||
`<a class='sls-troubleshoot-anchor'></a> [${$msg("obsidianLiveSyncSettingTab.linkTipsAndTroubleshooting")}](${topPath}) [${$msg("obsidianLiveSyncSettingTab.linkPageTop")}](${filename})\n\n${remoteTroubleShootMD}`,
|
`<a class='sls-troubleshoot-anchor'></a> [${$msg("obsidianLiveSyncSettingTab.linkTipsAndTroubleshooting")}](${topPath}) [${$msg("obsidianLiveSyncSettingTab.linkPageTop")}](${filename})\n\n${remoteTroubleShootMD}`,
|
||||||
troubleShootEl,
|
troubleShootEl,
|
||||||
`${rawRepoURI}`,
|
`${rawRepoURI}`,
|
||||||
this.plugin
|
this.lifetimeComponent
|
||||||
);
|
);
|
||||||
// Menu
|
// Menu
|
||||||
troubleShootEl.querySelector<HTMLAnchorElement>(".sls-troubleshoot-anchor")?.parentElement?.setCssStyles({
|
troubleShootEl.querySelector<HTMLAnchorElement>(".sls-troubleshoot-anchor")?.parentElement?.setCssStyles({
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { type Writable, writable, get } from "svelte/store";
|
|||||||
* Props passed to Svelte panels, containing a writable port
|
* Props passed to Svelte panels, containing a writable port
|
||||||
* to communicate with the panel
|
* to communicate with the panel
|
||||||
*/
|
*/
|
||||||
export type SveltePanelProps<T = any> = {
|
export type SveltePanelProps<T = unknown> = {
|
||||||
port: Writable<T | undefined>;
|
port: Writable<T | undefined>;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ export type SveltePanelProps<T = any> = {
|
|||||||
* A class to manage a Svelte panel within Obsidian
|
* A class to manage a Svelte panel within Obsidian
|
||||||
* Especially useful for settings panels
|
* Especially useful for settings panels
|
||||||
*/
|
*/
|
||||||
export class SveltePanel<T = any> {
|
export class SveltePanel<T = unknown> {
|
||||||
private _mountedComponent: ReturnType<typeof mount>;
|
private _mountedComponent: ReturnType<typeof mount>;
|
||||||
private _componentValue = writable<T | undefined>(undefined);
|
private _componentValue = writable<T | undefined>(undefined);
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
} from "@lib/common/utils";
|
} from "@lib/common/utils";
|
||||||
import { getConfig, type AllSettingItemKey } from "./settingConstants";
|
import { getConfig, type AllSettingItemKey } from "./settingConstants";
|
||||||
import { LOG_LEVEL_NOTICE, Logger } from "octagonal-wheels/common/logger";
|
import { LOG_LEVEL_NOTICE, Logger } from "octagonal-wheels/common/logger";
|
||||||
|
import { isNotFoundError } from "@lib/common/utils.doc";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a summary of P2P configuration settings
|
* Generates a summary of P2P configuration settings
|
||||||
@@ -90,10 +91,10 @@ export function getSummaryFromPartialSettings(setting: Partial<ObsidianLiveSyncS
|
|||||||
export async function copyMigrationDocs(docName: string, dbFrom: PouchDB.Database, dbTo: PouchDB.Database) {
|
export async function copyMigrationDocs(docName: string, dbFrom: PouchDB.Database, dbTo: PouchDB.Database) {
|
||||||
try {
|
try {
|
||||||
const doc = await dbFrom.get(docName);
|
const doc = await dbFrom.get(docName);
|
||||||
delete (doc as any)._rev;
|
delete (doc as { _rev?: string })._rev;
|
||||||
await dbTo.put(doc);
|
await dbTo.put(doc);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if ((e as any).status === 404) {
|
if (isNotFoundError(e)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { fireAndForget, parseHeaderValues } from "@lib/common/utils";
|
|||||||
import { isCloudantURI } from "@lib/pouchdb/utils_couchdb";
|
import { isCloudantURI } from "@lib/pouchdb/utils_couchdb";
|
||||||
import { generateCredentialObject } from "@lib/replication/httplib";
|
import { generateCredentialObject } from "@lib/replication/httplib";
|
||||||
import { compatGlobal } from "@lib/common/coreEnvFunctions.ts";
|
import { compatGlobal } from "@lib/common/coreEnvFunctions.ts";
|
||||||
|
import { isUnauthorizedError } from "@lib/common/utils.doc";
|
||||||
|
|
||||||
export const checkConfig = async (
|
export const checkConfig = async (
|
||||||
checkResultDiv: HTMLDivElement | undefined,
|
checkResultDiv: HTMLDivElement | undefined,
|
||||||
@@ -260,8 +261,8 @@ export const checkConfig = async (
|
|||||||
addResult($msg("obsidianLiveSyncSettingTab.msgDone"), ["ob-btn-config-head"]);
|
addResult($msg("obsidianLiveSyncSettingTab.msgDone"), ["ob-btn-config-head"]);
|
||||||
addResult($msg("obsidianLiveSyncSettingTab.msgConnectionProxyNote"), ["ob-btn-config-info"]);
|
addResult($msg("obsidianLiveSyncSettingTab.msgConnectionProxyNote"), ["ob-btn-config-info"]);
|
||||||
Logger($msg("obsidianLiveSyncSettingTab.logCheckingConfigDone"), LOG_LEVEL_INFO);
|
Logger($msg("obsidianLiveSyncSettingTab.logCheckingConfigDone"), LOG_LEVEL_INFO);
|
||||||
} catch (ex: any) {
|
} catch (ex) {
|
||||||
if (ex?.status == 401) {
|
if (isUnauthorizedError(ex)) {
|
||||||
isSuccessful = false;
|
isSuccessful = false;
|
||||||
addResult($msg("obsidianLiveSyncSettingTab.errAccessForbidden"));
|
addResult($msg("obsidianLiveSyncSettingTab.errAccessForbidden"));
|
||||||
addResult($msg("obsidianLiveSyncSettingTab.errCannotContinueTest"));
|
addResult($msg("obsidianLiveSyncSettingTab.errCannotContinueTest"));
|
||||||
|
|||||||
@@ -22,17 +22,17 @@
|
|||||||
detectedIssues.push({ message: `Error during testAndFixSettings: ${e}`, result: "error", classes: [] });
|
detectedIssues.push({ message: `Error during testAndFixSettings: ${e}`, result: "error", classes: [] });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function isErrorResult(result: ConfigCheckResult): result is ResultError | ResultErrorMessage {
|
function isErrorResult(result: ConfigCheckResult): result is ResultError<unknown> | ResultErrorMessage {
|
||||||
return "result" in result && result.result === "error";
|
return "result" in result && result.result === "error";
|
||||||
}
|
}
|
||||||
function isFixableError(result: ConfigCheckResult): result is ResultError {
|
function isFixableError(result: ConfigCheckResult): result is ResultError<unknown> {
|
||||||
return isErrorResult(result) && "fix" in result && typeof result.fix === "function";
|
return isErrorResult(result) && "fix" in result && typeof result.fix === "function";
|
||||||
}
|
}
|
||||||
function isSuccessResult(result: ConfigCheckResult): result is { message: string; result: "ok"; value?: any } {
|
function isSuccessResult(result: ConfigCheckResult): result is { message: string; result: "ok"; value?: any } {
|
||||||
return "result" in result && result.result === "ok";
|
return "result" in result && result.result === "ok";
|
||||||
}
|
}
|
||||||
let processing = $state(false);
|
let processing = $state(false);
|
||||||
async function fixIssue(issue: ResultError) {
|
async function fixIssue(issue: ResultError<unknown>) {
|
||||||
try {
|
try {
|
||||||
processing = true;
|
processing = true;
|
||||||
await issue.fix();
|
await issue.fix();
|
||||||
|
|||||||
@@ -6,12 +6,17 @@ import { parseHeaderValues } from "@lib/common/utils";
|
|||||||
import { isCloudantURI } from "@lib/pouchdb/utils_couchdb";
|
import { isCloudantURI } from "@lib/pouchdb/utils_couchdb";
|
||||||
import { generateCredentialObject } from "@lib/replication/httplib";
|
import { generateCredentialObject } from "@lib/replication/httplib";
|
||||||
import { compatGlobal } from "@lib/common/coreEnvFunctions.ts";
|
import { compatGlobal } from "@lib/common/coreEnvFunctions.ts";
|
||||||
|
import { isUnauthorizedError } from "@lib/common/utils.doc";
|
||||||
|
|
||||||
export type ResultMessage = { message: string; classes: string[] };
|
export type ResultMessage = { message: string; classes: string[] };
|
||||||
export type ResultErrorMessage = { message: string; result: "error"; classes: string[] };
|
export type ResultErrorMessage = { message: string; result: "error"; classes: string[] };
|
||||||
export type ResultOk = { message: string; result: "ok"; value?: any };
|
export type ResultOk<T> = { message: string; result: "ok"; value?: T };
|
||||||
export type ResultError = { message: string; result: "error"; value: any; fixMessage: string; fix(): Promise<void> };
|
export type ResultError<T> = { message: string; result: "error"; value: T; fixMessage: string; fix(): Promise<void> };
|
||||||
export type ConfigCheckResult = ResultOk | ResultError | ResultMessage | ResultErrorMessage;
|
export type ConfigCheckResult<T = unknown, U = unknown> =
|
||||||
|
| ResultOk<T>
|
||||||
|
| ResultError<U>
|
||||||
|
| ResultMessage
|
||||||
|
| ResultErrorMessage;
|
||||||
/**
|
/**
|
||||||
* Compares two version strings to determine if the baseVersion is greater than or equal to the version.
|
* Compares two version strings to determine if the baseVersion is greater than or equal to the version.
|
||||||
* @param baseVersion a.b.c format
|
* @param baseVersion a.b.c format
|
||||||
@@ -37,7 +42,11 @@ function isGreaterThanOrEqual(baseVersion: string, version: string) {
|
|||||||
* @param value setting value to update
|
* @param value setting value to update
|
||||||
* @returns true if the update was successful, false otherwise
|
* @returns true if the update was successful, false otherwise
|
||||||
*/
|
*/
|
||||||
async function updateRemoteSetting(setting: ObsidianLiveSyncSettings, key: string, value: any) {
|
async function updateRemoteSetting(
|
||||||
|
setting: ObsidianLiveSyncSettings,
|
||||||
|
key: string,
|
||||||
|
value: string
|
||||||
|
): Promise<true | string> {
|
||||||
const customHeaders = parseHeaderValues(setting.couchDB_CustomHeaders);
|
const customHeaders = parseHeaderValues(setting.couchDB_CustomHeaders);
|
||||||
const credential = generateCredentialObject(setting);
|
const credential = generateCredentialObject(setting);
|
||||||
const res = await requestToCouchDBWithCredentials(
|
const res = await requestToCouchDBWithCredentials(
|
||||||
@@ -62,24 +71,29 @@ async function updateRemoteSetting(setting: ObsidianLiveSyncSettings, key: strin
|
|||||||
* @returns Array of ConfigCheckResult
|
* @returns Array of ConfigCheckResult
|
||||||
*/
|
*/
|
||||||
export const checkConfig = async (editingSettings: ObsidianLiveSyncSettings) => {
|
export const checkConfig = async (editingSettings: ObsidianLiveSyncSettings) => {
|
||||||
const result = [] as ConfigCheckResult[];
|
const result = [] as ConfigCheckResult<unknown, unknown>[];
|
||||||
const addMessage = (msg: string, classes: string[] = []) => {
|
const addMessage = (msg: string, classes: string[] = []) => {
|
||||||
result.push({ message: msg, classes });
|
result.push({ message: msg, classes });
|
||||||
};
|
};
|
||||||
const addSuccess = (msg: string, value?: any) => {
|
const addSuccess = <T>(msg: string, value?: T) => {
|
||||||
result.push({ message: msg, result: "ok", value });
|
result.push({ message: msg, result: "ok", value });
|
||||||
};
|
};
|
||||||
const _addError = (message: string, fixMessage: string, fix: () => Promise<void>, value?: any) => {
|
const _addError = <T>(message: string, fixMessage: string, fix: () => Promise<void>, value?: T) => {
|
||||||
result.push({ message, result: "error", fixMessage, fix, value });
|
result.push({ message, result: "error", fixMessage, fix, value });
|
||||||
};
|
};
|
||||||
const addErrorMessage = (msg: string, classes: string[] = []) => {
|
const addErrorMessage = (msg: string, classes: string[] = []) => {
|
||||||
result.push({ message: msg, result: "error", classes });
|
result.push({ message: msg, result: "error", classes });
|
||||||
};
|
};
|
||||||
|
|
||||||
const addError = (message: string, fixMessage: string, key: string, expected: any) => {
|
const addError = (message: string, fixMessage: string, key: string, expected: string) => {
|
||||||
_addError(message, fixMessage, async () => {
|
_addError(
|
||||||
await updateRemoteSetting(editingSettings, key, expected);
|
message,
|
||||||
});
|
fixMessage,
|
||||||
|
async () => {
|
||||||
|
await updateRemoteSetting(editingSettings, key, expected);
|
||||||
|
},
|
||||||
|
expected
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
addMessage($msg("obsidianLiveSyncSettingTab.logCheckingDbConfig"));
|
addMessage($msg("obsidianLiveSyncSettingTab.logCheckingDbConfig"));
|
||||||
@@ -281,8 +295,8 @@ export const checkConfig = async (editingSettings: ObsidianLiveSyncSettings) =>
|
|||||||
addMessage($msg("obsidianLiveSyncSettingTab.msgDone"), ["ob-btn-config-head"]);
|
addMessage($msg("obsidianLiveSyncSettingTab.msgDone"), ["ob-btn-config-head"]);
|
||||||
addMessage($msg("obsidianLiveSyncSettingTab.msgConnectionProxyNote"), ["ob-btn-config-info"]);
|
addMessage($msg("obsidianLiveSyncSettingTab.msgConnectionProxyNote"), ["ob-btn-config-info"]);
|
||||||
addMessage($msg("obsidianLiveSyncSettingTab.logCheckingConfigDone"));
|
addMessage($msg("obsidianLiveSyncSettingTab.logCheckingConfigDone"));
|
||||||
} catch (ex: any) {
|
} catch (ex) {
|
||||||
if (ex?.status == 401) {
|
if (isUnauthorizedError(ex)) {
|
||||||
addErrorMessage($msg("obsidianLiveSyncSettingTab.errAccessForbidden"));
|
addErrorMessage($msg("obsidianLiveSyncSettingTab.errAccessForbidden"));
|
||||||
addErrorMessage($msg("obsidianLiveSyncSettingTab.errCannotContinueTest"));
|
addErrorMessage($msg("obsidianLiveSyncSettingTab.errCannotContinueTest"));
|
||||||
addMessage($msg("obsidianLiveSyncSettingTab.logCheckingConfigDone"));
|
addMessage($msg("obsidianLiveSyncSettingTab.logCheckingConfigDone"));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { InjectableAPIService } from "@lib/services/implements/injectable/InjectableAPIService";
|
import { InjectableAPIService } from "@lib/services/implements/injectable/InjectableAPIService";
|
||||||
import type { ObsidianServiceContext } from "@lib/services/implements/obsidian/ObsidianServiceContext";
|
import type { ObsidianServiceContext } from "@lib/services/implements/obsidian/ObsidianServiceContext";
|
||||||
import { Platform, type Command, type ViewCreator } from "obsidian";
|
import { Platform, type Command, type ViewCreator } from "@/deps.ts";
|
||||||
import { ObsHttpHandler } from "@/modules/essentialObsidian/APILib/ObsHttpHandler";
|
import { ObsHttpHandler } from "@/modules/essentialObsidian/APILib/ObsHttpHandler";
|
||||||
import { ObsidianConfirm } from "./ObsidianConfirm";
|
import { ObsidianConfirm } from "./ObsidianConfirm";
|
||||||
import type { Confirm } from "@lib/interfaces/Confirm";
|
import type { Confirm } from "@lib/interfaces/Confirm";
|
||||||
@@ -122,14 +122,15 @@ export class ObsidianAPIService extends InjectableAPIService<ObsidianServiceCont
|
|||||||
return this.context.plugin.addCommand(command) as TCommand;
|
return this.context.plugin.addCommand(command) as TCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
registerWindow(type: string, factory: ViewCreator): void {
|
registerWindow<T>(type: string, factory: (leaf: T) => unknown): void {
|
||||||
return this.context.plugin.registerView(type, factory);
|
return this.context.plugin.registerView(type, factory as ViewCreator);
|
||||||
}
|
}
|
||||||
addRibbonIcon(icon: string, title: string, callback: (evt: MouseEvent) => any): HTMLElement {
|
|
||||||
|
addRibbonIcon(icon: string, title: string, callback: (evt: MouseEvent) => unknown): HTMLElement {
|
||||||
return this.context.plugin.addRibbonIcon(icon, title, callback);
|
return this.context.plugin.addRibbonIcon(icon, title, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
registerProtocolHandler(action: string, handler: (params: Record<string, string>) => any): void {
|
registerProtocolHandler(action: string, handler: (params: Record<string, string>) => unknown): void {
|
||||||
return this.context.plugin.registerObsidianProtocolHandler(action, handler);
|
return this.context.plugin.registerObsidianProtocolHandler(action, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ export async function deleteFlagFile(host: NecessaryServices<never, "storageAcce
|
|||||||
}
|
}
|
||||||
const REMOTE_KEEP_CURRENT = "Use active remote";
|
const REMOTE_KEEP_CURRENT = "Use active remote";
|
||||||
const REMOTE_CANCEL = "Cancel";
|
const REMOTE_CANCEL = "Cancel";
|
||||||
async function askAndActivateRemoteDatabase(host: NecessaryServices<"UI" | "setting", any>, log: LogFunction) {
|
async function askAndActivateRemoteDatabase(host: NecessaryServices<"UI" | "setting", never>, log: LogFunction) {
|
||||||
const settings = host.services.setting.currentSettings();
|
const settings = host.services.setting.currentSettings();
|
||||||
if (settings.remoteConfigurations && Object.keys(settings.remoteConfigurations).length > 1) {
|
if (settings.remoteConfigurations && Object.keys(settings.remoteConfigurations).length > 1) {
|
||||||
const message =
|
const message =
|
||||||
@@ -216,7 +216,7 @@ export function createFetchAllFlagHandler(
|
|||||||
* @returns updated configuration if applied, otherwise null.
|
* @returns updated configuration if applied, otherwise null.
|
||||||
*/
|
*/
|
||||||
export async function adjustSettingToRemote(
|
export async function adjustSettingToRemote(
|
||||||
host: NecessaryServices<"tweakValue" | "UI" | "setting", any>,
|
host: NecessaryServices<"tweakValue" | "UI" | "setting", never>,
|
||||||
log: LogFunction,
|
log: LogFunction,
|
||||||
config: ObsidianLiveSyncSettings
|
config: ObsidianLiveSyncSettings
|
||||||
) {
|
) {
|
||||||
@@ -243,7 +243,7 @@ export async function adjustSettingToRemote(
|
|||||||
const necessary = extractObject(TweakValuesShouldMatchedTemplate, remoteTweaks);
|
const necessary = extractObject(TweakValuesShouldMatchedTemplate, remoteTweaks);
|
||||||
// Check if any necessary tweak value is different from current config.
|
// Check if any necessary tweak value is different from current config.
|
||||||
const differentItems = Object.entries(necessary).filter(([key, value]) => {
|
const differentItems = Object.entries(necessary).filter(([key, value]) => {
|
||||||
return (config as any)[key] !== value;
|
return config[key as keyof ObsidianLiveSyncSettings] !== value;
|
||||||
});
|
});
|
||||||
if (differentItems.length === 0) {
|
if (differentItems.length === 0) {
|
||||||
log("Remote configuration matches local configuration. No changes applied.", LOG_LEVEL_NOTICE);
|
log("Remote configuration matches local configuration. No changes applied.", LOG_LEVEL_NOTICE);
|
||||||
@@ -260,7 +260,7 @@ export async function adjustSettingToRemote(
|
|||||||
|
|
||||||
config = {
|
config = {
|
||||||
...config,
|
...config,
|
||||||
...Object.fromEntries(differentItems),
|
...(Object.fromEntries(differentItems) as Partial<ObsidianLiveSyncSettings>),
|
||||||
} satisfies ObsidianLiveSyncSettings;
|
} satisfies ObsidianLiveSyncSettings;
|
||||||
await host.services.setting.applyExternalSettings(config, true);
|
await host.services.setting.applyExternalSettings(config, true);
|
||||||
log("Remote configuration applied.", LOG_LEVEL_NOTICE);
|
log("Remote configuration applied.", LOG_LEVEL_NOTICE);
|
||||||
@@ -277,7 +277,7 @@ export async function adjustSettingToRemote(
|
|||||||
* @param config current configuration to retrieve remote preferred config
|
* @param config current configuration to retrieve remote preferred config
|
||||||
*/
|
*/
|
||||||
export async function adjustSettingToRemoteIfNeeded(
|
export async function adjustSettingToRemoteIfNeeded(
|
||||||
host: NecessaryServices<"tweakValue" | "UI" | "setting", any>,
|
host: NecessaryServices<"tweakValue" | "UI" | "setting", never>,
|
||||||
log: LogFunction,
|
log: LogFunction,
|
||||||
extra: { preventFetchingConfig: boolean },
|
extra: { preventFetchingConfig: boolean },
|
||||||
config: ObsidianLiveSyncSettings
|
config: ObsidianLiveSyncSettings
|
||||||
@@ -309,7 +309,7 @@ export async function adjustSettingToRemoteIfNeeded(
|
|||||||
* @returns result of the process, or false if error occurs.
|
* @returns result of the process, or false if error occurs.
|
||||||
*/
|
*/
|
||||||
export async function processVaultInitialisation(
|
export async function processVaultInitialisation(
|
||||||
host: NecessaryServices<"setting", any>,
|
host: NecessaryServices<"setting", never>,
|
||||||
log: LogFunction,
|
log: LogFunction,
|
||||||
proc: () => Promise<boolean>,
|
proc: () => Promise<boolean>,
|
||||||
keepSuspending = false
|
keepSuspending = false
|
||||||
@@ -341,7 +341,7 @@ export async function processVaultInitialisation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function verifyAndUnlockSuspension(
|
export async function verifyAndUnlockSuspension(
|
||||||
host: NecessaryServices<"setting" | "appLifecycle" | "UI", any>,
|
host: NecessaryServices<"setting" | "appLifecycle" | "UI", never>,
|
||||||
log: LogFunction
|
log: LogFunction
|
||||||
) {
|
) {
|
||||||
if (!host.services.setting.currentSettings().suspendFileWatching) {
|
if (!host.services.setting.currentSettings().suspendFileWatching) {
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import { TFile, TFolder } from "obsidian";
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export class ObsidianTypeGuardAdapter implements ITypeGuardAdapter<TFile, TFolder> {
|
export class ObsidianTypeGuardAdapter implements ITypeGuardAdapter<TFile, TFolder> {
|
||||||
isFile(file: any): file is TFile {
|
isFile(file: unknown): file is TFile {
|
||||||
return file instanceof TFile;
|
return file instanceof TFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
isFolder(item: any): item is TFolder {
|
isFolder(item: unknown): item is TFolder {
|
||||||
return item instanceof TFolder;
|
return item instanceof TFolder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import type { TFile, App, TFolder } from "obsidian";
|
|||||||
/**
|
/**
|
||||||
* Vault adapter implementation for Obsidian
|
* Vault adapter implementation for Obsidian
|
||||||
*/
|
*/
|
||||||
export class ObsidianVaultAdapter implements IVaultAdapter<TFile> {
|
export class ObsidianVaultAdapter implements IVaultAdapter<TFile, TFolder> {
|
||||||
constructor(private app: App) {}
|
constructor(private app: App) {}
|
||||||
|
|
||||||
async read(file: TFile): Promise<string> {
|
async read(file: TFile): Promise<string> {
|
||||||
@@ -55,7 +55,7 @@ export class ObsidianVaultAdapter implements IVaultAdapter<TFile> {
|
|||||||
return await this.app.vault.trash(file, force);
|
return await this.app.vault.trash(file, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
trigger(name: string, ...data: any[]): any {
|
trigger(name: string, ...data: unknown[]): void {
|
||||||
return this.app.vault.trigger(name, ...data);
|
return this.app.vault.trigger(name, ...data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,11 +26,7 @@ for (const sourceFile of project.getSourceFiles()) {
|
|||||||
const posixFilePath = toPosixPath(filePath);
|
const posixFilePath = toPosixPath(filePath);
|
||||||
|
|
||||||
if (!posixFilePath.startsWith(posixSrc)) continue;
|
if (!posixFilePath.startsWith(posixSrc)) continue;
|
||||||
if (
|
if (posixFilePath.includes("/_test/") || posixFilePath.endsWith(".spec.ts") || posixFilePath.endsWith(".test.ts")) {
|
||||||
posixFilePath.includes("/_test/") ||
|
|
||||||
posixFilePath.endsWith(".spec.ts") ||
|
|
||||||
posixFilePath.endsWith(".test.ts")
|
|
||||||
) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ for (const sourceFile of project.getSourceFiles()) {
|
|||||||
const posixFilePath = toPosixPath(filePath);
|
const posixFilePath = toPosixPath(filePath);
|
||||||
|
|
||||||
if (!posixFilePath.startsWith(posixSrc)) continue;
|
if (!posixFilePath.startsWith(posixSrc)) continue;
|
||||||
if (posixFilePath.includes("/_test/") || posixFilePath.endsWith(".spec.ts") || posixFilePath.endsWith(".test.ts")) continue;
|
if (posixFilePath.includes("/_test/") || posixFilePath.endsWith(".spec.ts") || posixFilePath.endsWith(".test.ts"))
|
||||||
|
continue;
|
||||||
|
|
||||||
// Find AsExpression (expr as Type) and TypeAssertion (<Type>expr)
|
// Find AsExpression (expr as Type) and TypeAssertion (<Type>expr)
|
||||||
const asExpressions = sourceFile.getDescendantsOfKind(SyntaxKind.AsExpression);
|
const asExpressions = sourceFile.getDescendantsOfKind(SyntaxKind.AsExpression);
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ for (const sourceFile of project.getSourceFiles()) {
|
|||||||
|
|
||||||
for (const impDecl of importDeclarations) {
|
for (const impDecl of importDeclarations) {
|
||||||
const specifier = impDecl.getModuleSpecifierValue();
|
const specifier = impDecl.getModuleSpecifierValue();
|
||||||
|
|
||||||
// Check if it's a Node.js built-in module we want to redirect
|
// Check if it's a Node.js built-in module we want to redirect
|
||||||
let exportedName = "";
|
let exportedName = "";
|
||||||
if (specifier === "fs/promises" || specifier === "node:fs/promises") {
|
if (specifier === "fs/promises" || specifier === "node:fs/promises") {
|
||||||
@@ -92,11 +92,11 @@ for (const sourceFile of project.getSourceFiles()) {
|
|||||||
|
|
||||||
if (targetImports.length > 0) {
|
if (targetImports.length > 0) {
|
||||||
console.log(`File: ${posixFilePath.slice(posixProjectRoot.length + 1)}`);
|
console.log(`File: ${posixFilePath.slice(posixProjectRoot.length + 1)}`);
|
||||||
|
|
||||||
for (const { impDecl, exportedName, localName } of targetImports) {
|
for (const { impDecl, exportedName, localName } of targetImports) {
|
||||||
const { line } = sourceFile.getLineAndColumnAtPos(impDecl.getStart());
|
const { line } = sourceFile.getLineAndColumnAtPos(impDecl.getStart());
|
||||||
console.log(` Line ${line}: Redirecting "${impDecl.getText()}"`);
|
console.log(` Line ${line}: Redirecting "${impDecl.getText()}"`);
|
||||||
|
|
||||||
if (exportedName === localName) {
|
if (exportedName === localName) {
|
||||||
namedImportsToAdd.push(exportedName);
|
namedImportsToAdd.push(exportedName);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ for (const sourceFile of project.getSourceFiles()) {
|
|||||||
const posixFilePath = toPosixPath(filePath);
|
const posixFilePath = toPosixPath(filePath);
|
||||||
|
|
||||||
if (!posixFilePath.startsWith(posixSrc)) continue;
|
if (!posixFilePath.startsWith(posixSrc)) continue;
|
||||||
if (posixFilePath.includes("/_test/") || posixFilePath.endsWith(".spec.ts") || posixFilePath.endsWith(".test.ts")) continue;
|
if (posixFilePath.includes("/_test/") || posixFilePath.endsWith(".spec.ts") || posixFilePath.endsWith(".test.ts"))
|
||||||
|
continue;
|
||||||
|
|
||||||
let fileModified = false;
|
let fileModified = false;
|
||||||
|
|
||||||
@@ -51,10 +52,11 @@ for (const sourceFile of project.getSourceFiles()) {
|
|||||||
if (varDec) {
|
if (varDec) {
|
||||||
const varName = varDec.getName();
|
const varName = varDec.getName();
|
||||||
// Count references within the catch clause itself
|
// Count references within the catch clause itself
|
||||||
const count = catchClause.getDescendantsOfKind(SyntaxKind.Identifier)
|
const count = catchClause
|
||||||
.filter((id) => id.getText() === varName)
|
.getDescendantsOfKind(SyntaxKind.Identifier)
|
||||||
.length;
|
.filter((id) => id.getText() === varName).length;
|
||||||
if (count === 1) { // Only the declaration itself
|
if (count === 1) {
|
||||||
|
// Only the declaration itself
|
||||||
catchVarsToRemove.push(varDec);
|
catchVarsToRemove.push(varDec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,10 +88,11 @@ for (const sourceFile of project.getSourceFiles()) {
|
|||||||
for (const namedImport of namedImports) {
|
for (const namedImport of namedImports) {
|
||||||
const importName = namedImport.getAliasNode()?.getText() ?? namedImport.getName();
|
const importName = namedImport.getAliasNode()?.getText() ?? namedImport.getName();
|
||||||
// Count references in the entire file
|
// Count references in the entire file
|
||||||
const count = sourceFile.getDescendantsOfKind(SyntaxKind.Identifier)
|
const count = sourceFile
|
||||||
.filter((id) => id.getText() === importName)
|
.getDescendantsOfKind(SyntaxKind.Identifier)
|
||||||
.length;
|
.filter((id) => id.getText() === importName).length;
|
||||||
if (count === 1) { // Only the import specifier itself
|
if (count === 1) {
|
||||||
|
// Only the import specifier itself
|
||||||
importsToRemove.push({ namedImport, impDecl });
|
importsToRemove.push({ namedImport, impDecl });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-3
@@ -9,10 +9,17 @@ import fs from "node:fs";
|
|||||||
import { platform } from "node:process";
|
import { platform } from "node:process";
|
||||||
|
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
function readJson(filePath: string) {
|
||||||
|
if (!fs.existsSync(filePath)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
||||||
|
}
|
||||||
|
|
||||||
const manifestJson = JSON.parse(fs.readFileSync("./manifest.json") + "");
|
const manifestJson = readJson(path.resolve(__dirname, "manifest.json"));
|
||||||
const packageJson = JSON.parse(fs.readFileSync("./package.json") + "");
|
const packageJson = readJson(path.resolve(__dirname, "package.json"));
|
||||||
const updateInfo = JSON.stringify(fs.readFileSync("./updates.md") + "");
|
const updatesPath = path.resolve(__dirname, "updates.md");
|
||||||
|
const updateInfo = JSON.stringify(fs.existsSync(updatesPath) ? fs.readFileSync(updatesPath, "utf-8") : "");
|
||||||
|
|
||||||
// const moduleAliasPlugin = {
|
// const moduleAliasPlugin = {
|
||||||
// name: "module-alias",
|
// name: "module-alias",
|
||||||
|
|||||||
Reference in New Issue
Block a user