export function createMonograph()

in controlplane/src/core/bufservices/monograph/createMonograph.ts [25:207]


export function createMonograph(
  opts: RouterOptions,
  req: CreateMonographRequest,
  ctx: HandlerContext,
): Promise<PlainMessage<CreateMonographResponse>> {
  let logger = getLogger(ctx, opts.logger);

  return handleError<PlainMessage<CreateMonographResponse>>(ctx, logger, async () => {
    return await opts.db.transaction(async (tx) => {
      req.namespace = req.namespace || DefaultNamespace;

      const authContext = await opts.authenticator.authenticate(ctx.requestHeader);
      logger = enrichLogger(ctx, logger, authContext);

      const orgRepo = new OrganizationRepository(logger, opts.db, opts.billingDefaultPlanId);
      const fedGraphRepo = new FederatedGraphRepository(logger, opts.db, authContext.organizationId);
      const subgraphRepo = new SubgraphRepository(logger, opts.db, authContext.organizationId);
      const auditLogRepo = new AuditLogRepository(opts.db);
      const namespaceRepo = new NamespaceRepository(opts.db, authContext.organizationId);

      if (!authContext.hasWriteAccess) {
        return {
          response: {
            code: EnumStatusCode.ERR,
            details: `The user doesn't have the permissions to perform this operation`,
          },
        };
      }

      const namespace = await namespaceRepo.byName(req.namespace);
      if (!namespace) {
        return {
          response: {
            code: EnumStatusCode.ERR_NOT_FOUND,
            details: `Could not find namespace ${req.namespace}`,
          },
        };
      }

      if (await fedGraphRepo.exists(req.name, req.namespace)) {
        return {
          response: {
            code: EnumStatusCode.ERR_ALREADY_EXISTS,
            details: `Graph '${req.name}' already exists in the namespace`,
          },
        };
      }

      if (await subgraphRepo.exists(req.name, req.namespace)) {
        return {
          response: {
            code: EnumStatusCode.ERR_ALREADY_EXISTS,
            details: `The subgraph ${req.name} being created for the monograph already exists in the namespace`,
          },
        };
      }

      if (!isValidUrl(req.routingUrl)) {
        return {
          response: {
            code: EnumStatusCode.ERR,
            details: `Routing URL is not a valid URL`,
          },
        };
      }

      if (!isValidUrl(req.graphUrl)) {
        return {
          response: {
            code: EnumStatusCode.ERR,
            details: `Graph URL is not a valid URL`,
          },
        };
      }

      if (!isValidGraphName(req.name)) {
        return {
          response: {
            code: EnumStatusCode.ERR_INVALID_NAME,
            details: `The name of the monograph is invalid. Name should start and end with an alphanumeric character. Only '.', '_', '@', '/', and '-' are allowed as separators in between and must be between 1 and 100 characters in length.`,
          },
          compositionErrors: [],
          deploymentErrors: [],
          compositionWarnings: [],
        };
      }

      const count = await fedGraphRepo.count();

      const feature = await orgRepo.getFeature({
        organizationId: authContext.organizationId,
        featureId: 'federated-graphs',
      });

      const limit = feature?.limit === -1 ? undefined : feature?.limit;

      if (limit && count >= limit) {
        return {
          response: {
            code: EnumStatusCode.ERR_LIMIT_REACHED,
            details: `The organization reached the limit of federated graphs and monographs`,
          },
        };
      }

      const label = createRandomInternalLabel();

      const labelMatchers = [joinLabel(label)];

      const subgraph = await subgraphRepo.create({
        name: req.name,
        namespace: req.namespace,
        namespaceId: namespace.id,
        createdBy: authContext.userId,
        labels: [label],
        routingUrl: req.graphUrl,
        isEventDrivenGraph: false,
        readme: req.readme,
        subscriptionUrl: req.subscriptionUrl,
        subscriptionProtocol:
          req.subscriptionProtocol === undefined ? undefined : formatSubscriptionProtocol(req.subscriptionProtocol),
        websocketSubprotocol:
          req.websocketSubprotocol === undefined ? undefined : formatWebsocketSubprotocol(req.websocketSubprotocol),
      });

      if (!subgraph) {
        return {
          response: {
            code: EnumStatusCode.ERR,
            details: `Could not create monograph`,
          },
        };
      }

      const graph = await fedGraphRepo.create({
        name: req.name,
        createdBy: authContext.userId,
        labelMatchers,
        routingUrl: req.routingUrl,
        readme: req.readme,
        namespace: req.namespace,
        namespaceId: namespace.id,
        admissionWebhookURL: req.admissionWebhookURL,
        admissionWebhookSecret: req.admissionWebhookSecret,
        supportsFederation: false,
      });

      if (!graph) {
        return {
          response: {
            code: EnumStatusCode.ERR,
            details: `Could not create monograph`,
          },
        };
      }

      await fedGraphRepo.createGraphCryptoKeyPairs({
        federatedGraphId: graph.id,
        organizationId: authContext.organizationId,
      });

      await auditLogRepo.addAuditLog({
        organizationId: authContext.organizationId,
        auditAction: 'monograph.created',
        action: 'created',
        actorId: authContext.userId,
        auditableType: 'monograph',
        auditableDisplayName: graph.name,
        actorDisplayName: authContext.userDisplayName,
        apiKeyName: authContext.apiKeyName,
        actorType: authContext.auth === 'api_key' ? 'api_key' : 'user',
        targetNamespaceId: graph.namespaceId,
        targetNamespaceDisplayName: graph.namespace,
      });

      return {
        response: {
          code: EnumStatusCode.OK,
        },
      };
    });
  });
}