114 lines
3.4 KiB
TypeScript
114 lines
3.4 KiB
TypeScript
import { customAlphabet } from "nanoid";
|
|
import { $transaction, prisma, PrismaClient } from "~/db.server";
|
|
import { env } from "~/env.server";
|
|
import { AuthenticatedEnvironment } from "../apiAuth.server";
|
|
import { workerQueue } from "../worker.server";
|
|
import { CreateEndpointError } from "./createEndpoint.server";
|
|
import { EndpointApi } from "../endpointApi.server";
|
|
import { RuntimeEnvironmentType } from "~/database-types";
|
|
|
|
const indexingHookIdentifier = customAlphabet("0123456789abcdefghijklmnopqrstuvxyz", 10);
|
|
|
|
export class ValidateCreateEndpointService {
|
|
#prismaClient: PrismaClient;
|
|
|
|
constructor(prismaClient: PrismaClient = prisma) {
|
|
this.#prismaClient = prismaClient;
|
|
}
|
|
|
|
public async call({ environment, url }: { environment: AuthenticatedEnvironment; url: string }) {
|
|
const endpointUrl = this.#normalizeEndpointUrl(url);
|
|
|
|
const client = new EndpointApi(environment.apiKey, endpointUrl);
|
|
|
|
const validationResult = await client.validate();
|
|
|
|
if (!validationResult.ok) {
|
|
throw new Error(validationResult.error);
|
|
}
|
|
|
|
try {
|
|
const result = await $transaction(this.#prismaClient, async (tx) => {
|
|
const endpoint = await tx.endpoint.upsert({
|
|
where: {
|
|
environmentId_slug: {
|
|
environmentId: environment.id,
|
|
slug: validationResult.endpointId,
|
|
},
|
|
},
|
|
include: {
|
|
environment: true,
|
|
},
|
|
create: {
|
|
environment: {
|
|
connect: {
|
|
id: environment.id,
|
|
},
|
|
},
|
|
organization: {
|
|
connect: {
|
|
id: environment.organizationId,
|
|
},
|
|
},
|
|
project: {
|
|
connect: {
|
|
id: environment.projectId,
|
|
},
|
|
},
|
|
slug: validationResult.endpointId,
|
|
url: endpointUrl,
|
|
indexingHookIdentifier: indexingHookIdentifier(),
|
|
version: validationResult.triggerVersion,
|
|
},
|
|
update: {
|
|
url: endpointUrl,
|
|
version: validationResult.triggerVersion,
|
|
},
|
|
});
|
|
|
|
const index = await tx.endpointIndex.create({
|
|
data: { endpointId: endpoint.id, status: "PENDING", source: "INTERNAL" },
|
|
});
|
|
|
|
// Kick off process to fetch the jobs for this index
|
|
await workerQueue.enqueue(
|
|
"performEndpointIndexing",
|
|
{
|
|
id: index.id,
|
|
},
|
|
{
|
|
tx,
|
|
maxAttempts:
|
|
endpoint.environment.type === RuntimeEnvironmentType.DEVELOPMENT ? 1 : undefined,
|
|
}
|
|
);
|
|
|
|
return endpoint;
|
|
});
|
|
|
|
return result;
|
|
} catch (error) {
|
|
if (error instanceof Error) {
|
|
throw new CreateEndpointError("FAILED_UPSERT", error.message);
|
|
} else {
|
|
throw new CreateEndpointError("FAILED_UPSERT", "Something went wrong");
|
|
}
|
|
}
|
|
}
|
|
|
|
// If the endpoint URL points to localhost, and the RUNTIME_PLATFORM is docker-compose, then we need to rewrite the host to host.docker.internal
|
|
// otherwise we shouldn't change anything
|
|
#normalizeEndpointUrl(url: string) {
|
|
if (env.RUNTIME_PLATFORM === "docker-compose") {
|
|
const urlObj = new URL(url);
|
|
|
|
if (urlObj.hostname === "localhost") {
|
|
urlObj.hostname = "host.docker.internal";
|
|
return urlObj.toString();
|
|
}
|
|
}
|
|
|
|
return url;
|
|
}
|
|
}
|