feat(integrations): add app linking (#4338)

This commit is contained in:
Meier Lukas
2025-10-24 20:21:27 +02:00
committed by GitHub
parent 6f0b5d7e04
commit 172db0e3f9
47 changed files with 6791 additions and 158 deletions

View File

@@ -1,7 +1,4 @@
import { decryptSecret } from "@homarr/common/server";
import type { Modify } from "@homarr/common/types";
import type { Integration as DbIntegration } from "@homarr/db/schema";
import type { IntegrationKind, IntegrationSecretKind } from "@homarr/definitions";
import type { IntegrationKind } from "@homarr/definitions";
import { AdGuardHomeIntegration } from "../adguard-home/adguard-home-integration";
import { CodebergIntegration } from "../codeberg/codeberg-integration";
@@ -62,20 +59,6 @@ export const createIntegrationAsync = async <TKind extends keyof typeof integrat
return new creator(integration) as IntegrationInstanceOfKind<TKind>;
};
export const createIntegrationAsyncFromSecrets = <TKind extends keyof typeof integrationCreators>(
integration: Modify<DbIntegration, { kind: TKind }> & {
secrets: { kind: IntegrationSecretKind; value: `${string}.${string}` }[];
},
) => {
return createIntegrationAsync({
...integration,
decryptedSecrets: integration.secrets.map((secret) => ({
...secret,
value: decryptSecret(secret.value),
})),
});
};
type IntegrationInstance = new (integration: IntegrationInput) => Integration;
// factories are an array, to differentiate in js between class constructors and functions

View File

@@ -17,6 +17,7 @@ export interface IntegrationInput {
id: string;
name: string;
url: string;
externalUrl: string | null;
decryptedSecrets: IntegrationSecret[];
}
@@ -54,8 +55,12 @@ export abstract class Integration {
return this.integration.decryptedSecrets.some((secret) => secret.kind === kind);
}
protected url(path: `/${string}`, queryParams?: Record<string, string | Date | number | boolean>) {
const baseUrl = removeTrailingSlash(this.integration.url);
private createUrl(
inputUrl: string,
path: `/${string}`,
queryParams?: Record<string, string | Date | number | boolean>,
) {
const baseUrl = removeTrailingSlash(inputUrl);
const url = new URL(`${baseUrl}${path}`);
if (queryParams) {
@@ -66,6 +71,13 @@ export abstract class Integration {
return url;
}
protected url(path: `/${string}`, queryParams?: Record<string, string | Date | number | boolean>) {
return this.createUrl(this.integration.url, path, queryParams);
}
protected externalUrl(path: `/${string}`, queryParams?: Record<string, string | Date | number | boolean>) {
return this.createUrl(this.integration.externalUrl ?? this.integration.url, path, queryParams);
}
public async testConnectionAsync(): Promise<TestingResult> {
try {