"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildAdminServerModel = buildAdminServerModel;
const _ = require("lodash");
const graphql_subscriptions_1 = require("graphql-subscriptions");
const rule_deserialization_1 = require("../rules/rule-deserialization");
const REQUEST_INITIATED_TOPIC = 'request-initiated';
const REQUEST_RECEIVED_TOPIC = 'request-received';
const RESPONSE_COMPLETED_TOPIC = 'response-completed';
const WEBSOCKET_REQUEST_TOPIC = 'websocket-request';
const WEBSOCKET_ACCEPTED_TOPIC = 'websocket-accepted';
const WEBSOCKET_MESSAGE_RECEIVED_TOPIC = 'websocket-message-received';
const WEBSOCKET_MESSAGE_SENT_TOPIC = 'websocket-message-sent';
const WEBSOCKET_CLOSE_TOPIC = 'websocket-close';
const REQUEST_ABORTED_TOPIC = 'request-aborted';
const TLS_PASSTHROUGH_OPENED_TOPIC = 'tls-passthrough-opened';
const TLS_PASSTHROUGH_CLOSED_TOPIC = 'tls-passthrough-closed';
const TLS_CLIENT_ERROR_TOPIC = 'tls-client-error';
const CLIENT_ERROR_TOPIC = 'client-error';
const RULE_EVENT_TOPIC = 'rule-event';
async function buildMockedEndpointData(endpoint) {
    return {
        id: endpoint.id,
        explanation: endpoint.toString(true),
        seenRequests: await endpoint.getSeenRequests(),
        isPending: await endpoint.isPending()
    };
}
function buildAdminServerModel(mockServer, stream, ruleParameters) {
    const pubsub = new graphql_subscriptions_1.PubSub();
    mockServer.on('request-initiated', (evt) => {
        pubsub.publish(REQUEST_INITIATED_TOPIC, {
            requestInitiated: evt
        });
    });
    mockServer.on('request', (evt) => {
        pubsub.publish(REQUEST_RECEIVED_TOPIC, {
            requestReceived: evt
        });
    });
    mockServer.on('response', (evt) => {
        pubsub.publish(RESPONSE_COMPLETED_TOPIC, {
            responseCompleted: evt
        });
    });
    mockServer.on('websocket-request', (evt) => {
        pubsub.publish(WEBSOCKET_REQUEST_TOPIC, {
            webSocketRequest: evt
        });
    });
    mockServer.on('websocket-accepted', (evt) => {
        pubsub.publish(WEBSOCKET_ACCEPTED_TOPIC, {
            webSocketAccepted: evt
        });
    });
    mockServer.on('websocket-message-received', (evt) => {
        pubsub.publish(WEBSOCKET_MESSAGE_RECEIVED_TOPIC, {
            webSocketMessageReceived: evt
        });
    });
    mockServer.on('websocket-message-sent', (evt) => {
        pubsub.publish(WEBSOCKET_MESSAGE_SENT_TOPIC, {
            webSocketMessageSent: evt
        });
    });
    mockServer.on('websocket-close', (evt) => {
        pubsub.publish(WEBSOCKET_CLOSE_TOPIC, {
            webSocketClose: evt
        });
    });
    mockServer.on('abort', (evt) => {
        pubsub.publish(REQUEST_ABORTED_TOPIC, {
            requestAborted: Object.assign(evt, {
                // Backward compat: old clients expect this to be present. In future this can be
                // removed and abort events can lose the 'body' in the schema.
                body: Buffer.alloc(0)
            })
        });
    });
    mockServer.on('tls-passthrough-opened', (evt) => {
        pubsub.publish(TLS_PASSTHROUGH_OPENED_TOPIC, {
            tlsPassthroughOpened: evt
        });
    });
    mockServer.on('tls-passthrough-closed', (evt) => {
        pubsub.publish(TLS_PASSTHROUGH_CLOSED_TOPIC, {
            tlsPassthroughClosed: evt
        });
    });
    mockServer.on('tls-client-error', (evt) => {
        pubsub.publish(TLS_CLIENT_ERROR_TOPIC, {
            failedTlsRequest: evt
        });
    });
    mockServer.on('client-error', (evt) => {
        pubsub.publish(CLIENT_ERROR_TOPIC, {
            failedClientRequest: evt
        });
    });
    mockServer.on('rule-event', (evt) => {
        pubsub.publish(RULE_EVENT_TOPIC, {
            ruleEvent: evt
        });
    });
    return {
        Query: {
            mockedEndpoints: async () => {
                return Promise.all((await mockServer.getMockedEndpoints()).map(buildMockedEndpointData));
            },
            pendingEndpoints: async () => {
                return Promise.all((await mockServer.getPendingEndpoints()).map(buildMockedEndpointData));
            },
            mockedEndpoint: async (__, { id }) => {
                let endpoint = _.find(await mockServer.getMockedEndpoints(), (endpoint) => {
                    return endpoint.id === id;
                });
                if (!endpoint)
                    return null;
                return buildMockedEndpointData(endpoint);
            }
        },
        Mutation: {
            addRule: async (__, { input }) => {
                return mockServer.addRequestRule((0, rule_deserialization_1.deserializeRuleData)(input, stream, ruleParameters));
            },
            addRules: async (__, { input }) => {
                return mockServer.addRequestRules(...input.map((rule) => (0, rule_deserialization_1.deserializeRuleData)(rule, stream, ruleParameters)));
            },
            setRules: async (__, { input }) => {
                return mockServer.setRequestRules(...input.map((rule) => (0, rule_deserialization_1.deserializeRuleData)(rule, stream, ruleParameters)));
            },
            setFallbackRule: async (__, { input }) => {
                // Deprecated endpoint, but preserved for API backward compat
                const ruleData = (0, rule_deserialization_1.deserializeRuleData)(input, stream, ruleParameters);
                return mockServer.addRequestRules({
                    ...ruleData,
                    priority: 0
                }).then((rules) => rules[0]);
            },
            addWebSocketRule: async (__, { input }) => {
                return mockServer.addWebSocketRule((0, rule_deserialization_1.deserializeWebSocketRuleData)(input, stream, ruleParameters));
            },
            addWebSocketRules: async (__, { input }) => {
                return mockServer.addWebSocketRules(...input.map((rule) => (0, rule_deserialization_1.deserializeWebSocketRuleData)(rule, stream, ruleParameters)));
            },
            setWebSocketRules: async (__, { input }) => {
                return mockServer.setWebSocketRules(...input.map((rule) => (0, rule_deserialization_1.deserializeWebSocketRuleData)(rule, stream, ruleParameters)));
            }
        },
        Subscription: {
            requestInitiated: {
                subscribe: () => pubsub.asyncIterator(REQUEST_INITIATED_TOPIC)
            },
            requestReceived: {
                subscribe: () => pubsub.asyncIterator(REQUEST_RECEIVED_TOPIC)
            },
            responseCompleted: {
                subscribe: () => pubsub.asyncIterator(RESPONSE_COMPLETED_TOPIC)
            },
            webSocketRequest: {
                subscribe: () => pubsub.asyncIterator(WEBSOCKET_REQUEST_TOPIC)
            },
            webSocketAccepted: {
                subscribe: () => pubsub.asyncIterator(WEBSOCKET_ACCEPTED_TOPIC)
            },
            webSocketMessageReceived: {
                subscribe: () => pubsub.asyncIterator(WEBSOCKET_MESSAGE_RECEIVED_TOPIC)
            },
            webSocketMessageSent: {
                subscribe: () => pubsub.asyncIterator(WEBSOCKET_MESSAGE_SENT_TOPIC)
            },
            webSocketClose: {
                subscribe: () => pubsub.asyncIterator(WEBSOCKET_CLOSE_TOPIC)
            },
            requestAborted: {
                subscribe: () => pubsub.asyncIterator(REQUEST_ABORTED_TOPIC)
            },
            tlsPassthroughOpened: {
                subscribe: () => pubsub.asyncIterator(TLS_PASSTHROUGH_OPENED_TOPIC)
            },
            tlsPassthroughClosed: {
                subscribe: () => pubsub.asyncIterator(TLS_PASSTHROUGH_CLOSED_TOPIC)
            },
            failedTlsRequest: {
                subscribe: () => pubsub.asyncIterator(TLS_CLIENT_ERROR_TOPIC)
            },
            failedClientRequest: {
                subscribe: () => pubsub.asyncIterator(CLIENT_ERROR_TOPIC)
            },
            ruleEvent: {
                subscribe: () => pubsub.asyncIterator(RULE_EVENT_TOPIC)
            }
        },
        Request: {
            body: (request) => {
                return request.body.buffer;
            }
        },
        Response: {
            body: (response) => {
                return response.body.buffer;
            }
        },
        ClientError: {
            response: (error) => {
                if (error.response === 'aborted')
                    return undefined;
                else
                    return error.response;
            }
        }
    };
}
//# sourceMappingURL=mockttp-admin-model.js.map