mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-06-21 05:40:14 +00:00
define workspace
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"tasks": {
|
||||
"dev": "deno run --watch --allow-net main.ts"
|
||||
},
|
||||
"imports": {
|
||||
"@std/assert": "jsr:@std/assert@1"
|
||||
}
|
||||
}
|
||||
Generated
+69
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"version": "5",
|
||||
"specifiers": {
|
||||
"npm:ts-morph@*": "28.0.0",
|
||||
"npm:ts-morph@latest": "28.0.0"
|
||||
},
|
||||
"npm": {
|
||||
"@ts-morph/common@0.29.0": {
|
||||
"integrity": "sha512-35oUmphHbJvQ/+UTwFNme/t2p3FoKiGJ5auTjjpNTop2dyREspirjMy82PLSC1pnDJ8ah1GU98hwpVt64YXQsg==",
|
||||
"dependencies": [
|
||||
"minimatch",
|
||||
"path-browserify",
|
||||
"tinyglobby"
|
||||
]
|
||||
},
|
||||
"balanced-match@4.0.4": {
|
||||
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="
|
||||
},
|
||||
"brace-expansion@5.0.6": {
|
||||
"integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
|
||||
"dependencies": [
|
||||
"balanced-match"
|
||||
]
|
||||
},
|
||||
"code-block-writer@13.0.3": {
|
||||
"integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg=="
|
||||
},
|
||||
"fdir@6.5.0_picomatch@4.0.4": {
|
||||
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
|
||||
"dependencies": [
|
||||
"picomatch"
|
||||
],
|
||||
"optionalPeers": [
|
||||
"picomatch"
|
||||
]
|
||||
},
|
||||
"minimatch@10.2.5": {
|
||||
"integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
|
||||
"dependencies": [
|
||||
"brace-expansion"
|
||||
]
|
||||
},
|
||||
"path-browserify@1.0.1": {
|
||||
"integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="
|
||||
},
|
||||
"picomatch@4.0.4": {
|
||||
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="
|
||||
},
|
||||
"tinyglobby@0.2.16": {
|
||||
"integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
|
||||
"dependencies": [
|
||||
"fdir",
|
||||
"picomatch"
|
||||
]
|
||||
},
|
||||
"ts-morph@28.0.0": {
|
||||
"integrity": "sha512-Wp3tnZ2bzwxyTZMtgWVzXDfm7lB1Drz+y9DmmYH/L702PQhPyVrp3pkou3yIz4qjS14GY9kcpmLiOOMvl8oG1g==",
|
||||
"dependencies": [
|
||||
"@ts-morph/common",
|
||||
"code-block-writer"
|
||||
]
|
||||
}
|
||||
},
|
||||
"workspace": {
|
||||
"dependencies": [
|
||||
"jsr:@std/assert@1"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
// Delete references to utils.ts and replace them with new imports based on the importMap.
|
||||
// Use this script by running `deno run --allow-read --allow-write --allow-run refactor-import-utils.ts` from the utilsdeno directory.
|
||||
import { Project } from "npm:ts-morph";
|
||||
|
||||
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-run refactor-import-utils.ts --run\n"
|
||||
);
|
||||
}
|
||||
|
||||
// const project = new Project({ tsConfigFilePath: "../src/apps/cli/tsconfig.json" });
|
||||
const project = new Project({ tsConfigFilePath: "../tsconfig.json" });
|
||||
|
||||
const importMap = new Map<string, string>();
|
||||
|
||||
const targetFiles = [
|
||||
"utils.concurrency.ts",
|
||||
"utils.timer.ts",
|
||||
"utils.notations.ts",
|
||||
"utils.database.ts",
|
||||
"utils.regexp.ts",
|
||||
"utils.settings.ts",
|
||||
"utils.patch.ts",
|
||||
"utils.misc.ts",
|
||||
];
|
||||
|
||||
// 1. Map exports from our newly created subfiles
|
||||
for (const sourceFile of project.getSourceFiles()) {
|
||||
const filePath = sourceFile.getFilePath();
|
||||
const fileName = sourceFile.getBaseName();
|
||||
if (filePath.includes("src/lib/src/common/") && targetFiles.includes(fileName)) {
|
||||
const exports = sourceFile.getExportedDeclarations();
|
||||
for (const [name] of exports) {
|
||||
const relativePath = filePath.split("src/lib/src/")[1].replace(/\.ts$/, "");
|
||||
importMap.set(name, `@lib/${relativePath}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Map exports/imports of octagonal-wheels in utils.ts
|
||||
const utilsFile = project.getSourceFile("src/lib/src/common/utils.ts");
|
||||
if (utilsFile) {
|
||||
// Parse imports from octagonal-wheels
|
||||
for (const imp of utilsFile.getImportDeclarations()) {
|
||||
const moduleSpec = imp.getModuleSpecifierValue();
|
||||
if (moduleSpec.startsWith("octagonal-wheels")) {
|
||||
for (const namedImport of imp.getNamedImports()) {
|
||||
importMap.set(namedImport.getName(), moduleSpec);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Parse export declarations from octagonal-wheels
|
||||
for (const exp of utilsFile.getExportDeclarations()) {
|
||||
const moduleSpec = exp.getModuleSpecifierValue();
|
||||
if (moduleSpec && moduleSpec.startsWith("octagonal-wheels")) {
|
||||
for (const namedExport of exp.getNamedExports()) {
|
||||
importMap.set(namedExport.getName(), moduleSpec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Built importMap with ${importMap.size} mappings.\n`);
|
||||
|
||||
let modifiedFilesCount = 0;
|
||||
|
||||
// 3. Loop through all source files and replace imports
|
||||
for (const sourceFile of project.getSourceFiles()) {
|
||||
let fileModified = false;
|
||||
const imports = sourceFile.getImportDeclarations();
|
||||
|
||||
for (const imp of imports) {
|
||||
const moduleSpec = imp.getModuleSpecifierValue();
|
||||
const isUtilsImport =
|
||||
moduleSpec === "@lib/common/utils" ||
|
||||
moduleSpec === "@lib/common/utils.ts" ||
|
||||
moduleSpec.endsWith("/common/utils") ||
|
||||
moduleSpec.endsWith("/common/utils.ts");
|
||||
|
||||
if (isUtilsImport) {
|
||||
const namedImports = imp.getNamedImports();
|
||||
const defaultImport = imp.getDefaultImport();
|
||||
|
||||
const importsToReplace: Record<string, { name: string; newPath: string; isTypeOnly: boolean }[]> = {};
|
||||
for (const namedImport of namedImports) {
|
||||
const name = namedImport.getName();
|
||||
let newPath = importMap.get(name);
|
||||
if (newPath) {
|
||||
// If original ended with .ts and the new path starts with @lib, keep .ts
|
||||
if (moduleSpec.endsWith(".ts") && newPath.startsWith("@lib/")) {
|
||||
newPath = newPath + ".ts";
|
||||
}
|
||||
if (!importsToReplace[newPath]) {
|
||||
importsToReplace[newPath] = [];
|
||||
}
|
||||
importsToReplace[newPath].push({
|
||||
name,
|
||||
newPath,
|
||||
isTypeOnly: namedImport.isTypeOnly() || imp.isTypeOnly(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(importsToReplace).length > 0 || (defaultImport && importMap.has(defaultImport.getText()))) {
|
||||
fileModified = true;
|
||||
|
||||
console.log(`File: ${sourceFile.getFilePath().split("obsidian-livesync/")[1]}`);
|
||||
console.log(` Old: ${imp.getText()}`);
|
||||
}
|
||||
|
||||
if (!isDryRun) {
|
||||
// Apply replacements
|
||||
for (const newPath in importsToReplace) {
|
||||
const isTypeOnly = importsToReplace[newPath].filter((i) => i.isTypeOnly);
|
||||
if (isTypeOnly.length > 0) {
|
||||
sourceFile.insertImportDeclaration(imp.getChildIndex(), {
|
||||
namedImports: isTypeOnly.map((i) => i.name),
|
||||
moduleSpecifier: newPath,
|
||||
isTypeOnly: true,
|
||||
});
|
||||
}
|
||||
const isValueImport = importsToReplace[newPath].filter((i) => !i.isTypeOnly);
|
||||
if (isValueImport.length > 0) {
|
||||
sourceFile.insertImportDeclaration(imp.getChildIndex(), {
|
||||
namedImports: isValueImport.map((i) => i.name),
|
||||
moduleSpecifier: newPath,
|
||||
isTypeOnly: false,
|
||||
});
|
||||
}
|
||||
for (const { name } of importsToReplace[newPath]) {
|
||||
const namedImport = imp.getNamedImports().find((ni) => ni.getName() === name);
|
||||
if (namedImport) {
|
||||
namedImport.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// In dry run, just print what it would do
|
||||
for (const newPath in importsToReplace) {
|
||||
const names = importsToReplace[newPath].map((i) => i.name).join(", ");
|
||||
console.log(` -> Would import { ${names} } from "${newPath}"`);
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultImport) {
|
||||
const name = defaultImport.getText();
|
||||
let newPath = importMap.get(name);
|
||||
if (newPath) {
|
||||
if (moduleSpec.endsWith(".ts") && newPath.startsWith("@lib/")) {
|
||||
newPath = newPath + ".ts";
|
||||
}
|
||||
if (!isDryRun) {
|
||||
sourceFile.insertImportDeclaration(imp.getChildIndex(), {
|
||||
defaultImport: name,
|
||||
moduleSpecifier: newPath,
|
||||
isTypeOnly: imp.isTypeOnly(),
|
||||
});
|
||||
imp.removeDefaultImport();
|
||||
} else {
|
||||
console.log(` -> Would import default ${name} from "${newPath}"`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isDryRun) {
|
||||
if (imp.getNamedImports().length === 0 && !imp.getDefaultImport()) {
|
||||
imp.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fileModified) {
|
||||
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.");
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
// Delete references to types.ts and replace them with new imports based on the importMap. It will also split imports if some are type-only and some are value imports.
|
||||
// Use this script by running `deno run --allow-read --allow-write --allow-run refactor-imports.ts` from the utilsdeno directory. It will read all source files, find imports from types.ts, and replace them with the new paths based on the importMap. Make sure to review the changes before saving, as it will modify your source files.
|
||||
import { Project } from "npm:ts-morph";
|
||||
|
||||
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-run refactor-import-utils.ts --run\n"
|
||||
);
|
||||
}
|
||||
|
||||
// const project = new Project({ tsConfigFilePath: "../src/apps/cli/tsconfig.json" });
|
||||
const project = new Project({ tsConfigFilePath: "../tsconfig.json" });
|
||||
|
||||
const importMap = new Map<string, string>();
|
||||
// Build a map of types moved out of Models.
|
||||
// Under src/lib/src/common/models.
|
||||
for (const sourceFile of project.getSourceFiles()) {
|
||||
if (sourceFile.getFilePath().includes("src/lib/src/common/models")) {
|
||||
const exports = sourceFile.getExportedDeclarations();
|
||||
for (const [name, declarations] of exports) {
|
||||
for (const declaration of declarations) {
|
||||
if (
|
||||
// declaration.getKindName() === "TypeAliasDeclaration" ||
|
||||
// declaration.getKindName() === "InterfaceDeclaration" ||
|
||||
// declaration.getKindName() === "EnumDeclaration" ||
|
||||
true
|
||||
) {
|
||||
// console.log(`Found type export in ${sourceFile.getFilePath()}:`, name);
|
||||
const relativePath = sourceFile.getFilePath().split("src/lib/src/")[1].replace(/\.ts$/, "");
|
||||
importMap.set(name, `@lib/${relativePath}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Extras
|
||||
|
||||
importMap.set("LOG_LEVEL_NOTICE", "@lib/common/logger");
|
||||
importMap.set("LOG_LEVEL_VERBOSE", "@lib/common/logger");
|
||||
importMap.set("LOG_LEVEL_INFO", "@lib/common/logger");
|
||||
importMap.set("LOG_LEVEL_DEBUG", "@lib/common/logger");
|
||||
importMap.set("LOG_LEVEL_URGENT", "@lib/common/logger");
|
||||
importMap.set("LOG_LEVEL", "@lib/common/logger");
|
||||
importMap.set("Logger", "@lib/common/logger");
|
||||
|
||||
// console.log("Import map:", importMap);
|
||||
|
||||
// Loop through all files that import from types.ts.
|
||||
for (const sourceFile of project.getSourceFiles()) {
|
||||
const imports = sourceFile.getImportDeclarations();
|
||||
// if import from types.ts and the file is pointing `/lib/src/common/types.ts` (resolved), then we will check if the imported names exist in the importMap, if yes, we will replace the import path with the new path from importMap.
|
||||
|
||||
for (const imp of imports) {
|
||||
const moduleSpecifier = imp.getModuleSpecifierValue();
|
||||
if (moduleSpecifier.endsWith("types") || moduleSpecifier.endsWith("types.ts")) {
|
||||
const filePath = sourceFile.getFilePath();
|
||||
const lineNumber = imp.getStartLineNumber();
|
||||
const resolvedModule = imp.getModuleSpecifierSourceFile();
|
||||
if (!resolvedModule || !resolvedModule.getFilePath().includes("/lib/src/common/types.ts")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Collect imports from types.ts.
|
||||
const namedImports = imp.getNamedImports();
|
||||
const defaultImport = imp.getDefaultImport();
|
||||
console.log(`Found import in ${filePath} at line ${lineNumber}:`, {
|
||||
namedImports: namedImports.map((ni) => ni.getText()),
|
||||
defaultImport: defaultImport ? defaultImport.getText() : null,
|
||||
});
|
||||
// Group imports by their names and generate new import paths based on the importMap
|
||||
const importsToReplace: Record<string, { name: string; newPath: string; isTypeOnly: boolean }[]> = {};
|
||||
for (const namedImport of namedImports) {
|
||||
const name = namedImport.getName();
|
||||
const newPath = importMap.get(name);
|
||||
if (newPath) {
|
||||
console.log(
|
||||
`Will replace import of ${name} in ${filePath} at line ${lineNumber} with new path:`,
|
||||
newPath
|
||||
);
|
||||
if (!importsToReplace[newPath]) {
|
||||
importsToReplace[newPath] = [];
|
||||
}
|
||||
importsToReplace[newPath].push({
|
||||
name,
|
||||
newPath,
|
||||
isTypeOnly: namedImport.isTypeOnly() || imp.isTypeOnly(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// For each import, generate a new path from importMap and replace it.
|
||||
// Split the import when it needs to become multiple imports.
|
||||
|
||||
for (const newPath in importsToReplace) {
|
||||
// First, handle type-only imports.
|
||||
const isTypeOnly = importsToReplace[newPath].filter((i) => i.isTypeOnly);
|
||||
if (isTypeOnly.length > 0) {
|
||||
sourceFile.insertImportDeclaration(imp.getChildIndex(), {
|
||||
namedImports: isTypeOnly.map((i) => i.name),
|
||||
moduleSpecifier: newPath,
|
||||
isTypeOnly: true,
|
||||
});
|
||||
}
|
||||
// Then, handle non-type-only imports.
|
||||
const isValueImport = importsToReplace[newPath].filter((i) => !i.isTypeOnly);
|
||||
if (isValueImport.length > 0) {
|
||||
sourceFile.insertImportDeclaration(imp.getChildIndex(), {
|
||||
namedImports: isValueImport.map((i) => i.name),
|
||||
moduleSpecifier: newPath,
|
||||
isTypeOnly: false,
|
||||
});
|
||||
}
|
||||
// Remove the replaced named imports from the old import.
|
||||
for (const { name } of importsToReplace[newPath]) {
|
||||
const namedImport = imp.getNamedImports().find((ni) => ni.getName() === name);
|
||||
if (namedImport) {
|
||||
namedImport.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
// If there is also a default import and it exists in importMap, replace it too.
|
||||
if (defaultImport) {
|
||||
const name = defaultImport.getText();
|
||||
const newPath = importMap.get(name);
|
||||
|
||||
if (newPath) {
|
||||
console.log(
|
||||
`Replacing default import of ${name} in ${filePath} at line ${lineNumber} with new path:`,
|
||||
newPath
|
||||
);
|
||||
// Add the new import statement.
|
||||
sourceFile.insertImportDeclaration(imp.getChildIndex(), {
|
||||
defaultImport: name,
|
||||
moduleSpecifier: newPath,
|
||||
isTypeOnly: imp.isTypeOnly(),
|
||||
});
|
||||
// Remove the default import from the old import.
|
||||
imp.removeDefaultImport();
|
||||
}
|
||||
}
|
||||
if (imp.getNamedImports().length === 0 && !imp.getDefaultImport()) {
|
||||
// Delete the entire import statement if nothing remains.
|
||||
imp.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save everything at the end.
|
||||
if (!isDryRun) {
|
||||
project.saveSync();
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import { Project, SyntaxKind } from "npm:ts-morph";
|
||||
|
||||
function processFile(filePath: string) {
|
||||
const project = new Project();
|
||||
const sourceFile = project.addSourceFileAtPath(filePath);
|
||||
|
||||
// 1. Collect all 'any' type nodes in the file
|
||||
const anyTypeNodes = sourceFile.getDescendantsOfKind(SyntaxKind.AnyKeyword);
|
||||
const sourceText = sourceFile.getFullText();
|
||||
const lineBreak = sourceText.includes("\r\n") ? "\r\n" : "\n";
|
||||
const lines = sourceText.split(/\r?\n/);
|
||||
const targetLines = new Set<number>();
|
||||
|
||||
// 2. Collect the line numbers that contain 'any'
|
||||
anyTypeNodes.forEach((anyNode: any) => {
|
||||
const { line } = sourceFile.getLineAndColumnAtPos(anyNode.getStart());
|
||||
targetLines.add(line - 1);
|
||||
});
|
||||
|
||||
// 3. Add an inline disable only to lines that contain 'any'
|
||||
for (const lineIndex of targetLines) {
|
||||
const line = lines[lineIndex];
|
||||
if (!line) {
|
||||
continue;
|
||||
}
|
||||
if (line.includes("eslint-disable-line @typescript-eslint/no-explicit-any")) {
|
||||
continue;
|
||||
}
|
||||
lines[lineIndex] = `${line} // eslint-disable-line @typescript-eslint/no-explicit-any`;
|
||||
}
|
||||
|
||||
const updatedSourceText = lines.join(lineBreak);
|
||||
|
||||
// Output the result
|
||||
return updatedSourceText;
|
||||
}
|
||||
|
||||
const targetDir = `./_types/`;
|
||||
|
||||
async function processDir(dirPath: string) {
|
||||
for await (const entry of Deno.readDir(dirPath)) {
|
||||
if (entry.isDirectory) {
|
||||
await processDir(`${dirPath}/${entry.name}`);
|
||||
}
|
||||
if (entry.isFile && entry.name.endsWith(".d.ts")) {
|
||||
const filePath = `${dirPath}/${entry.name}`;
|
||||
console.log(`Processing: ${filePath}`);
|
||||
const updatedContent = processFile(filePath);
|
||||
// Write the file. To revert, regenerate it with npm run lib:build:types.
|
||||
await Deno.writeTextFile(filePath, updatedContent);
|
||||
|
||||
// console.log(`Updated content for ${filePath}:\n${updatedContent}\n`);
|
||||
console.log(`Processed: ${filePath}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await processDir(targetDir);
|
||||
Reference in New Issue
Block a user