You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
2.9 KiB
TypeScript
116 lines
2.9 KiB
TypeScript
type TODO_TypeDefinition = any;
|
|
|
|
class Application {
|
|
private constructor(private readonly data: any) {}
|
|
|
|
static createFromDefinition(data: any): Application {
|
|
return new Application(data);
|
|
}
|
|
|
|
get name(): string {
|
|
return this.data.appName;
|
|
}
|
|
get lastDeployedAt(): Date {
|
|
return new Date(this.currentVersion.timeStamp);
|
|
}
|
|
get imageName(): string {
|
|
return this.currentVersion.deployedImageName;
|
|
}
|
|
get dockerImage(): undefined | { name: string; tag: string; hubUrl: string } {
|
|
const match = this.imageName.match(/^(.*):(.*)$/);
|
|
if (!match || match[1].includes("/captain/")) {
|
|
return undefined;
|
|
}
|
|
|
|
const name = match[1];
|
|
return {
|
|
name: name,
|
|
tag: match[2],
|
|
hubUrl: name.includes("/")
|
|
? `https://hub.docker.com/r/${name}`
|
|
: `https://hub.docker.com/_/${name}`,
|
|
};
|
|
}
|
|
|
|
isOlderThan(days: number): boolean {
|
|
const daysInMs = days * 24 * 60 * 60 * 1000;
|
|
const now = Date.now();
|
|
return now - this.lastDeployedAt.getTime() > daysInMs;
|
|
}
|
|
|
|
toString(): string {
|
|
return JSON.stringify(this.data, null, 2);
|
|
}
|
|
|
|
private get currentVersion(): TODO_TypeDefinition {
|
|
return this.data.versions.find((version: { version: number }) => {
|
|
return version.version === this.data.deployedVersion;
|
|
});
|
|
}
|
|
}
|
|
|
|
class Caprover {
|
|
private authToken: string = "";
|
|
private readonly apiUrl: string;
|
|
|
|
constructor(readonly domain?: string, private readonly password?: string) {
|
|
if (!domain || !password) {
|
|
throw new Error("Missing domain or password");
|
|
}
|
|
this.apiUrl = `https://${domain}/api/v2`;
|
|
}
|
|
|
|
async getApps(): Promise<Application[]> {
|
|
const res = await this.fetch("/user/apps/appDefinitions").then((res) =>
|
|
res.json()
|
|
);
|
|
|
|
return (
|
|
res.data?.appDefinitions?.map(Application.createFromDefinition) ?? []
|
|
);
|
|
}
|
|
|
|
private async authenticate() {
|
|
if (this.authToken) {
|
|
return;
|
|
}
|
|
|
|
console.debug("Trying to authenticate at", this.apiUrl);
|
|
|
|
const authResponse = await fetch(`${this.apiUrl}/login`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
"x-namespace": "captain",
|
|
},
|
|
body: JSON.stringify({
|
|
password: this.password,
|
|
}),
|
|
}).then((res) => res.json());
|
|
|
|
this.authToken = authResponse?.data?.token;
|
|
if (!this.authToken) {
|
|
throw new Error(`Failed to authenticate at ${this.apiUrl}`);
|
|
}
|
|
console.debug("Authenticated successfully at", this.apiUrl, this.authToken);
|
|
}
|
|
|
|
private async fetch(path: string, options?: RequestInit) {
|
|
await this.authenticate();
|
|
|
|
console.debug("-> Caprover Fetching", path);
|
|
return fetch(`${this.apiUrl}${path}`, {
|
|
...options,
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
...(options?.headers || {}),
|
|
"x-namespace": "captain",
|
|
"x-captain-auth": this.authToken,
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
export { Application };
|
|
export default Caprover;
|