"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebHookSubscription2021 = exports.isWebHook2021Channel = void 0;
const LogUtil_1 = require("../../../logging/LogUtil");
const BadRequestHttpError_1 = require("../../../util/errors/BadRequestHttpError");
const ErrorUtil_1 = require("../../../util/errors/ErrorUtil");
const Vocabularies_1 = require("../../../util/Vocabularies");
const BaseChannelType_1 = require("../BaseChannelType");
function isWebHook2021Channel(channel) {
    return channel.type === Vocabularies_1.NOTIFY.WebHookSubscription2021;
}
exports.isWebHook2021Channel = isWebHook2021Channel;
/**
 * The notification channel type WebHookSubscription2021 as described in
 * https://github.com/solid/notifications/blob/main/webhook-subscription-2021.md
 *
 * Requires read permissions on a resource to be able to receive notifications.
 *
 * Also handles the `state` feature if present.
 */
class WebHookSubscription2021 extends BaseChannelType_1.BaseChannelType {
    /**
     * @param route - The route corresponding to the URL of the subscription service of this channel type.
     * @param webIdRoute - The route to the WebID that needs to be used when generating DPoP tokens for notifications.
     * @param stateHandler - The {@link StateHandler} that will be called after a successful subscription.
     * @param features - The features that need to be enabled for this channel type.
     */
    constructor(route, webIdRoute, stateHandler, features = BaseChannelType_1.DEFAULT_NOTIFICATION_FEATURES) {
        super(Vocabularies_1.NOTIFY.terms.WebHookSubscription2021, route, [...features, Vocabularies_1.NOTIFY.webhookAuth], 
        // Need to remember to remove `target` from the vocabulary again once this is updated to webhooks 2023,
        // as it is not actually part of the vocabulary.
        // Technically we should also require that this node is a named node,
        // but that would require clients to send `target: { '@id': 'http://example.com/target' }`,
        // which would make this more annoying so we are lenient here.
        // Could change in the future once this field is updated and part of the context.
        [{ path: Vocabularies_1.NOTIFY.target, minCount: 1, maxCount: 1 }]);
        this.logger = (0, LogUtil_1.getLoggerFor)(this);
        this.stateHandler = stateHandler;
        this.webId = webIdRoute.getPath();
    }
    getDescription() {
        const base = super.getDescription();
        return {
            ...base,
            [Vocabularies_1.NOTIFY.webid]: { id: this.webId },
        };
    }
    async initChannel(data, credentials) {
        // The WebID is used to verify who can unsubscribe
        const webId = credentials.agent?.webId;
        if (!webId) {
            throw new BadRequestHttpError_1.BadRequestHttpError('A WebHookSubscription2021 subscription request needs to be authenticated with a WebID.');
        }
        const subject = await this.validateSubscription(data);
        const channel = await this.quadsToChannel(data, subject);
        const target = data.getObjects(subject, Vocabularies_1.NOTIFY.terms.target, null)[0];
        return {
            ...channel,
            type: Vocabularies_1.NOTIFY.WebHookSubscription2021,
            webId,
            target: target.value,
            // eslint-disable-next-line @typescript-eslint/naming-convention
            unsubscribe_endpoint: channel.id,
        };
    }
    async toJsonLd(channel) {
        const json = await super.toJsonLd(channel);
        // We don't want to expose the WebID that initialized the notification channel.
        // This is not really specified either way in the spec so this might change in the future.
        delete json.webId;
        return json;
    }
    async completeChannel(channel) {
        try {
            // Send the state notification, if there is one
            await this.stateHandler.handleSafe({ channel });
        }
        catch (error) {
            this.logger.error(`Error emitting state notification: ${(0, ErrorUtil_1.createErrorMessage)(error)}`);
        }
    }
}
exports.WebHookSubscription2021 = WebHookSubscription2021;
//# sourceMappingURL=WebHookSubscription2021.js.map