From 88a8bcbd5ad798097067d57412737d6aa122e199 Mon Sep 17 00:00:00 2001 From: vorotamoroz Date: Wed, 17 Jun 2026 06:15:25 +0100 Subject: [PATCH] barrel node specific modules to summarise the warnings --- .../cli/adapters/NodeConversionAdapter.ts | 2 +- .../cli/adapters/NodeFileSystemAdapter.ts | 3 +- src/apps/cli/adapters/NodePathAdapter.ts | 2 +- src/apps/cli/adapters/NodeStorageAdapter.ts | 3 +- src/apps/cli/adapters/NodeVaultAdapter.ts | 3 +- src/apps/cli/commands/runCommand.ts | 3 +- src/apps/cli/commands/utils.ts | 3 +- src/apps/cli/main.ts | 8 +- .../managers/CLIStorageEventManagerAdapter.ts | 3 +- src/apps/cli/node-compat.ts | 12 ++ src/apps/cli/serviceModules/IgnoreRules.ts | 4 +- .../cli/services/NodeKeyValueDBService.ts | 3 +- src/apps/cli/services/NodeLocalStorage.ts | 3 +- src/apps/cli/services/NodeServiceHub.ts | 2 +- utilsdeno/README.md | 12 ++ utilsdeno/refactor-cli-node-imports.ts | 132 ++++++++++++++++++ 16 files changed, 169 insertions(+), 29 deletions(-) create mode 100644 src/apps/cli/node-compat.ts create mode 100644 utilsdeno/refactor-cli-node-imports.ts diff --git a/src/apps/cli/adapters/NodeConversionAdapter.ts b/src/apps/cli/adapters/NodeConversionAdapter.ts index 044abe2..be410e8 100644 --- a/src/apps/cli/adapters/NodeConversionAdapter.ts +++ b/src/apps/cli/adapters/NodeConversionAdapter.ts @@ -1,7 +1,7 @@ -import * as path from "path"; import type { UXFileInfoStub, UXFolderInfo } from "@lib/common/types"; import type { IConversionAdapter } from "@lib/serviceModules/adapters"; import type { NodeFile, NodeFolder } from "./NodeTypes"; +import { path } from "../node-compat"; /** * Conversion adapter implementation for Node.js diff --git a/src/apps/cli/adapters/NodeFileSystemAdapter.ts b/src/apps/cli/adapters/NodeFileSystemAdapter.ts index 34d434e..94662e8 100644 --- a/src/apps/cli/adapters/NodeFileSystemAdapter.ts +++ b/src/apps/cli/adapters/NodeFileSystemAdapter.ts @@ -1,5 +1,3 @@ -import * as fs from "fs/promises"; -import * as path from "path"; import type { FilePath, UXStat } from "@lib/common/types"; import type { IFileSystemAdapter } from "@lib/serviceModules/adapters"; import { NodePathAdapter } from "./NodePathAdapter"; @@ -8,6 +6,7 @@ import { NodeConversionAdapter } from "./NodeConversionAdapter"; import { NodeStorageAdapter } from "./NodeStorageAdapter"; import { NodeVaultAdapter } from "./NodeVaultAdapter"; import type { NodeFile, NodeFolder, NodeStat } from "./NodeTypes"; +import { fsPromises as fs, path } from "../node-compat"; /** * Complete file system adapter implementation for Node.js diff --git a/src/apps/cli/adapters/NodePathAdapter.ts b/src/apps/cli/adapters/NodePathAdapter.ts index fdad06a..1a30fbc 100644 --- a/src/apps/cli/adapters/NodePathAdapter.ts +++ b/src/apps/cli/adapters/NodePathAdapter.ts @@ -1,7 +1,7 @@ -import * as path from "path"; import type { FilePath } from "@lib/common/types"; import type { IPathAdapter } from "@lib/serviceModules/adapters"; import type { NodeFile } from "./NodeTypes"; +import { path } from "../node-compat"; /** * Path adapter implementation for Node.js diff --git a/src/apps/cli/adapters/NodeStorageAdapter.ts b/src/apps/cli/adapters/NodeStorageAdapter.ts index 1ed5685..c6f4992 100644 --- a/src/apps/cli/adapters/NodeStorageAdapter.ts +++ b/src/apps/cli/adapters/NodeStorageAdapter.ts @@ -1,8 +1,7 @@ -import * as fs from "fs/promises"; -import * as path from "path"; import type { UXDataWriteOptions } from "@lib/common/types"; import type { IStorageAdapter } from "@lib/serviceModules/adapters"; import type { NodeStat } from "./NodeTypes"; +import { fsPromises as fs, path } from "../node-compat"; /** * Storage adapter implementation for Node.js diff --git a/src/apps/cli/adapters/NodeVaultAdapter.ts b/src/apps/cli/adapters/NodeVaultAdapter.ts index 99e8d93..deb44e5 100644 --- a/src/apps/cli/adapters/NodeVaultAdapter.ts +++ b/src/apps/cli/adapters/NodeVaultAdapter.ts @@ -1,8 +1,7 @@ -import * as fs from "fs/promises"; -import * as path from "path"; import type { UXDataWriteOptions } from "@lib/common/types"; import type { IVaultAdapter } from "@lib/serviceModules/adapters"; import type { NodeFile, NodeFolder } from "./NodeTypes"; +import { fsPromises as fs, path } from "../node-compat"; /** * Vault adapter implementation for Node.js diff --git a/src/apps/cli/commands/runCommand.ts b/src/apps/cli/commands/runCommand.ts index 9ce1a2f..9f09bcc 100644 --- a/src/apps/cli/commands/runCommand.ts +++ b/src/apps/cli/commands/runCommand.ts @@ -1,5 +1,3 @@ -import * as fs from "fs/promises"; -import * as path from "path"; import { decodeSettingsFromSetupURI } from "@lib/API/processSetting"; import { configURIBase } from "@lib/common/models/shared.const"; import { @@ -19,6 +17,7 @@ import { collectPeers, openP2PHost, parseTimeoutSeconds, syncWithPeer } from "./ import { performFullScan } from "@lib/serviceFeatures/offlineScanner"; import { UnresolvedErrorManager } from "@lib/services/base/UnresolvedErrorManager"; import { compatGlobal } from "@lib/common/coreEnvFunctions.ts"; +import { fsPromises as fs, path } from "../node-compat"; function redactConnectionString(uri: string): string { return uri.replace(/\/\/([^@/]+)@/u, "//***@"); diff --git a/src/apps/cli/commands/utils.ts b/src/apps/cli/commands/utils.ts index b596a71..abf6b19 100644 --- a/src/apps/cli/commands/utils.ts +++ b/src/apps/cli/commands/utils.ts @@ -1,5 +1,4 @@ -import * as path from "path"; -import * as readline from "node:readline/promises"; +import { path, readline } from "../node-compat"; export function toArrayBuffer(data: Buffer): ArrayBuffer { return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength) as ArrayBuffer; diff --git a/src/apps/cli/main.ts b/src/apps/cli/main.ts index e6d878f..cc63a6b 100644 --- a/src/apps/cli/main.ts +++ b/src/apps/cli/main.ts @@ -1,10 +1,3 @@ -/** - * Self-hosted LiveSync CLI - * Command-line version of Self-hosted LiveSync plugin for syncing vaults without Obsidian - */ - -import * as fs from "fs/promises"; -import * as path from "path"; import { NodeServiceContext, NodeServiceHub } from "./services/NodeServiceHub"; import { configureNodeLocalStorage, ensureGlobalNodeLocalStorage } from "./services/NodeLocalStorage"; import { LiveSyncBaseCore } from "@/LiveSyncBaseCore"; @@ -27,6 +20,7 @@ import { getPathFromUXFileInfo } from "@lib/common/typeUtils"; import { stripAllPrefixes } from "@lib/string_and_binary/path"; import { IgnoreRules } from "./serviceModules/IgnoreRules"; import { useP2PReplicatorFeature } from "@lib/replication/trystero/useP2PReplicatorFeature"; +import { fsPromises as fs, path } from "./node-compat"; const SETTINGS_FILE = ".livesync/settings.json"; ensureGlobalNodeLocalStorage(); diff --git a/src/apps/cli/managers/CLIStorageEventManagerAdapter.ts b/src/apps/cli/managers/CLIStorageEventManagerAdapter.ts index 64452a5..69bbc7e 100644 --- a/src/apps/cli/managers/CLIStorageEventManagerAdapter.ts +++ b/src/apps/cli/managers/CLIStorageEventManagerAdapter.ts @@ -12,10 +12,9 @@ import type { import type { FileEventItemSentinel } from "@lib/managers/StorageEventManager"; import type { NodeFile, NodeFolder } from "@/apps/cli/adapters/NodeTypes"; import type { Stats } from "fs"; -import * as fs from "fs/promises"; -import * as path from "path"; import { watch as chokidarWatch, type FSWatcher } from "chokidar"; import type { IgnoreRules } from "@/apps/cli/serviceModules/IgnoreRules"; +import { fsPromises as fs, path } from "../node-compat"; /** * CLI-specific type guard adapter diff --git a/src/apps/cli/node-compat.ts b/src/apps/cli/node-compat.ts new file mode 100644 index 0000000..cf8338a --- /dev/null +++ b/src/apps/cli/node-compat.ts @@ -0,0 +1,12 @@ +/* eslint-disable obsidianmd/no-nodejs-builtins */ +import * as nodeFs from "node:fs"; +import * as nodeFsPromises from "node:fs/promises"; +import * as nodePath from "node:path"; +import * as nodeReadlinePromises from "node:readline/promises"; + +export { + nodeFs as fs, + nodeFsPromises as fsPromises, + nodePath as path, + nodeReadlinePromises as readline, +}; diff --git a/src/apps/cli/serviceModules/IgnoreRules.ts b/src/apps/cli/serviceModules/IgnoreRules.ts index 0b7fc41..62e0b79 100644 --- a/src/apps/cli/serviceModules/IgnoreRules.ts +++ b/src/apps/cli/serviceModules/IgnoreRules.ts @@ -1,7 +1,5 @@ -import * as fs from "fs/promises"; -import * as path from "path"; - import { minimatch } from "minimatch"; +import { fsPromises as fs, path } from "../node-compat"; /** * Loads and evaluates ignore rules from `.livesync/ignore` inside the vault. diff --git a/src/apps/cli/services/NodeKeyValueDBService.ts b/src/apps/cli/services/NodeKeyValueDBService.ts index 10b1626..87f54c5 100644 --- a/src/apps/cli/services/NodeKeyValueDBService.ts +++ b/src/apps/cli/services/NodeKeyValueDBService.ts @@ -7,8 +7,7 @@ import type { InjectableDatabaseEventService } from "@lib/services/implements/in import type { IVaultService } from "@lib/services/base/IService"; import type { SimpleStore } from "octagonal-wheels/databases/SimpleStoreBase"; import { createInstanceLogFunction } from "@lib/services/lib/logUtils"; -import * as nodeFs from "node:fs"; -import * as nodePath from "node:path"; +import { fs as nodeFs, path as nodePath } from "../node-compat"; const NODE_KV_TYPED_KEY = "__nodeKvType"; const NODE_KV_VALUES_KEY = "values"; diff --git a/src/apps/cli/services/NodeLocalStorage.ts b/src/apps/cli/services/NodeLocalStorage.ts index 3e96822..a4ba07d 100644 --- a/src/apps/cli/services/NodeLocalStorage.ts +++ b/src/apps/cli/services/NodeLocalStorage.ts @@ -1,5 +1,4 @@ -import * as nodeFs from "node:fs"; -import * as nodePath from "node:path"; +import { fs as nodeFs, path as nodePath } from "../node-compat"; type LocalStorageShape = { getItem(key: string): string | null; diff --git a/src/apps/cli/services/NodeServiceHub.ts b/src/apps/cli/services/NodeServiceHub.ts index 2aaa093..770d3bb 100644 --- a/src/apps/cli/services/NodeServiceHub.ts +++ b/src/apps/cli/services/NodeServiceHub.ts @@ -1,6 +1,5 @@ import type { AppLifecycleService, AppLifecycleServiceDependencies } from "@lib/services/base/AppLifecycleService"; import { ServiceContext } from "@lib/services/base/ServiceBase"; -import * as nodePath from "node:path"; import { ConfigServiceBrowserCompat } from "@lib/services/implements/browser/ConfigServiceBrowserCompat"; import { SvelteDialogManagerBase, type ComponentHasResult } from "@lib/services/implements/base/SvelteDialog"; import { UIService } from "@lib/services/implements/base/UIService"; @@ -25,6 +24,7 @@ import { NodeKeyValueDBService } from "./NodeKeyValueDBService"; import { NodeSettingService } from "./NodeSettingService"; import { DatabaseService } from "@lib/services/base/DatabaseService"; import type { ObsidianLiveSyncSettings } from "@lib/common/types"; +import { path as nodePath } from "../node-compat"; export class NodeServiceContext extends ServiceContext { databasePath: string; diff --git a/utilsdeno/README.md b/utilsdeno/README.md index 70d3a83..dc46fc4 100644 --- a/utilsdeno/README.md +++ b/utilsdeno/README.md @@ -93,6 +93,18 @@ Ensures that all import statements are standardised across the codebase, resolvi deno run --allow-read --allow-write --allow-env normalise-imports.ts ``` +### 7. CLI Node.js Import Redirection (`refactor-cli-node-imports.ts`) +Redirects direct Node.js built-in module imports (like `fs` and `path`) within the CLI codebase to use a single barrel file (`src/apps/cli/node-compat.ts`). + +* **Actions**: + * Finds imports of Node.js built-in APIs (`fs`, `fs/promises`, `path`, and `readline/promises`) in CLI source files. + * Replaces them with imports from the local `node-compat.ts` barrel file. + * This eliminates duplicate browser-targeted linter warnings on Node.js built-ins in the CLI workspace, keeping linter ignores consolidated. +* **Command**: + ```bash + deno run --allow-read --allow-write --allow-env refactor-cli-node-imports.ts + ``` + --- ## Safety and Exclusions diff --git a/utilsdeno/refactor-cli-node-imports.ts b/utilsdeno/refactor-cli-node-imports.ts new file mode 100644 index 0000000..1a828ce --- /dev/null +++ b/utilsdeno/refactor-cli-node-imports.ts @@ -0,0 +1,132 @@ +// Refactor Node.js imports in the CLI application to use the barrel compatibility file. +// Use this script by running `deno run --allow-read --allow-write --allow-env refactor-cli-node-imports.ts` from the utilsdeno directory. +// Run with --run flag to apply changes. +import { Project, SyntaxKind, Node } from "npm:ts-morph"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const isDryRun = !Deno.args.includes("--run"); + +if (isDryRun) { + console.log("=== DRY RUN MODE ==="); + console.log( + "To apply changes, run with: deno run --allow-read --allow-write --allow-env refactor-cli-node-imports.ts --run\n" + ); +} else { + console.log("=== RUN MODE: WILL MODIFY FILES ==="); +} + +const project = new Project({ tsConfigFilePath: "../tsconfig.json" }); +project.addSourceFilesAtPaths("../src/apps/cli/**/*.ts"); + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const projectRoot = path.resolve(__dirname, ".."); +const nodeCompatPath = path.resolve(projectRoot, "src", "apps", "cli", "node-compat.ts"); + +function toPosixPath(filePath: string): string { + return filePath.replace(/\\/g, "/"); +} + +const posixProjectRoot = toPosixPath(projectRoot); +const posixSrc = `${posixProjectRoot}/src`; + +function getRelativeImportPath(fromFile: string, toFile: string): string { + let rel = path.relative(path.dirname(fromFile), toFile); + rel = rel.replace(/\\/g, "/"); + if (!rel.startsWith(".") && !rel.startsWith("/")) { + rel = "./" + rel; + } + if (rel.endsWith(".ts")) { + rel = rel.slice(0, -3); + } + return rel; +} + +let modifiedFilesCount = 0; + +for (const sourceFile of project.getSourceFiles()) { + const filePath = sourceFile.getFilePath(); + const posixFilePath = toPosixPath(filePath); + + // Only process CLI source files under src/apps/cli/ + if (!posixFilePath.includes("/src/apps/cli/")) continue; + if ( + posixFilePath.endsWith("node-compat.ts") || + posixFilePath.endsWith("vite.config.ts") || + posixFilePath.endsWith(".spec.ts") || + posixFilePath.endsWith(".test.ts") || + posixFilePath.includes("/_test/") || + posixFilePath.includes("/testdeno/") || + posixFilePath.includes("/test/") + ) { + continue; + } + + const importDeclarations = sourceFile.getImportDeclarations(); + const targetImports: any[] = []; + const namedImportsToAdd: string[] = []; + + for (const impDecl of importDeclarations) { + const specifier = impDecl.getModuleSpecifierValue(); + + // Check if it's a Node.js built-in module we want to redirect + let exportedName = ""; + if (specifier === "fs/promises" || specifier === "node:fs/promises") { + exportedName = "fsPromises"; + } else if (specifier === "fs" || specifier === "node:fs") { + exportedName = "fs"; + } else if (specifier === "path" || specifier === "node:path") { + exportedName = "path"; + } else if (specifier === "node:readline/promises") { + exportedName = "readline"; + } + + if (exportedName) { + const localName = impDecl.getNamespaceImport()?.getText() || impDecl.getDefaultImport()?.getText(); + if (localName) { + targetImports.push({ impDecl, exportedName, localName }); + } + } + } + + if (targetImports.length > 0) { + console.log(`File: ${posixFilePath.slice(posixProjectRoot.length + 1)}`); + + for (const { impDecl, exportedName, localName } of targetImports) { + const { line } = sourceFile.getLineAndColumnAtPos(impDecl.getStart()); + console.log(` Line ${line}: Redirecting "${impDecl.getText()}"`); + + if (exportedName === localName) { + namedImportsToAdd.push(exportedName); + } else { + namedImportsToAdd.push(`${exportedName} as ${localName}`); + } + + if (!isDryRun) { + impDecl.remove(); + } + } + + const relImportPath = getRelativeImportPath(filePath, nodeCompatPath); + console.log(` Adding: import { ${namedImportsToAdd.join(", ")} } from "${relImportPath}"`); + + if (!isDryRun) { + sourceFile.addImportDeclaration({ + namedImports: namedImportsToAdd, + moduleSpecifier: relImportPath, + }); + } + + modifiedFilesCount++; + } +} + +console.log(`\nTotal files to modify: ${modifiedFilesCount}`); + +if (!isDryRun) { + project.saveSync(); + console.log("All changes successfully saved."); +} else { + console.log("Dry run complete. No changes were written to files."); +}