### Refactored

- `ModuleTargetFilter`, which was responsible for checking if a file is a target file, has been ported to a serviceFeature.
  - And also tests have been added. The middleware-style-power.
- `ModuleObsidianAPI` has been removed and implemented in `APIService` and `RemoteService`.
- Now `APIService` is responsible for the network-online-status, not `databaseService.managers.networkManager`.
This commit is contained in:
vorotamoroz
2026-02-25 09:38:31 +00:00
parent be1642f1c1
commit 19c03ec8d8
14 changed files with 92 additions and 546 deletions
+67 -1
View File
@@ -4,7 +4,7 @@ import { Platform, type Command, type ViewCreator } from "obsidian";
import { ObsHttpHandler } from "../essentialObsidian/APILib/ObsHttpHandler";
import { ObsidianConfirm } from "./ObsidianConfirm";
import type { Confirm } from "@lib/interfaces/Confirm";
import { requestUrl, type RequestUrlParam } from "@/deps";
// All Services will be migrated to be based on Plain Services, not Injectable Services.
// This is a migration step.
@@ -102,7 +102,73 @@ export class ObsidianAPIService extends InjectableAPIService<ObsidianServiceCont
addRibbonIcon(icon: string, title: string, callback: (evt: MouseEvent) => any): HTMLElement {
return this.context.plugin.addRibbonIcon(icon, title, callback);
}
registerProtocolHandler(action: string, handler: (params: Record<string, string>) => any): void {
return this.context.plugin.registerObsidianProtocolHandler(action, handler);
}
/**
* In Obsidian, we will use the native `requestUrl` function as the default fetch handler,
* to address unavoidable CORS issues.
*/
override async nativeFetch(req: string | Request, opts?: RequestInit): Promise<Response> {
const url = typeof req === "string" ? req : req.url;
let body: string | ArrayBuffer | undefined = undefined;
const method =
typeof opts?.method === "string"
? opts.method
: req instanceof Request && typeof req.method === "string"
? req.method
: "GET";
if (typeof req !== "string") {
if (opts?.body) {
body = typeof opts.body === "string" ? opts.body : await new Response(opts.body).arrayBuffer();
} else if (req.body) {
body = await new Response(req.body).arrayBuffer();
}
} else {
body = opts?.body as string;
}
const reqHeaders = new Headers(req instanceof Request ? req.headers : {});
const optHeaders = {} as Record<string, string>;
// Merge headers from the Request object and the options, with options taking precedence
reqHeaders.forEach((value, key) => {
optHeaders[key] = value;
});
if (opts && "headers" in opts) {
if (opts.headers instanceof Headers) {
// For Compatibility, mostly headers.entries() is supported, but not all environments.
opts.headers.forEach((value, key) => {
optHeaders[key] = value;
});
} else {
for (const [key, value] of Object.entries(opts.headers as Record<string, string>)) {
optHeaders[key] = value;
}
}
}
const transformedHeaders = { ...optHeaders };
// Delete headers that should not be sent by native fetch,
// they are controlled by the browser and may cause CORS preflight failure if sent manually.
delete transformedHeaders["host"];
delete transformedHeaders["Host"];
delete transformedHeaders["content-length"];
delete transformedHeaders["Content-Length"];
const contentType =
transformedHeaders["content-type"] ?? transformedHeaders["Content-Type"] ?? "application/json";
const requestParam: RequestUrlParam = {
url,
method: method,
body: body,
headers: transformedHeaders,
contentType: contentType,
};
const r = await requestUrl({ ...requestParam, throw: false });
return new Response(r.arrayBuffer, {
headers: r.headers,
status: r.status,
statusText: `${r.status}`,
});
}
}
+5 -1
View File
@@ -33,7 +33,6 @@ export class ObsidianServiceHub extends InjectableServiceHub<ObsidianServiceCont
const conflict = new ObsidianConflictService(context);
const fileProcessing = new ObsidianFileProcessingService(context);
const remote = new ObsidianRemoteService(context);
const tweakValue = new ObsidianTweakValueService(context);
const setting = new ObsidianSettingService(context, {
@@ -42,6 +41,11 @@ export class ObsidianServiceHub extends InjectableServiceHub<ObsidianServiceCont
const appLifecycle = new ObsidianAppLifecycleService(context, {
settingService: setting,
});
const remote = new ObsidianRemoteService(context, {
APIService: API,
appLifecycle: appLifecycle,
setting: setting,
});
const vault = new ObsidianVaultService(context, {
settingService: setting,
APIService: API,