All files / fastify/src coherent-fastify.js

21.87% Statements 7/32
28.57% Branches 4/14
42.85% Functions 3/7
21.87% Lines 7/32

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126                                                2x     2x                   2x                                                   2x                                       2x                     1x                                                   1x          
/**
 * Fastify integration for Coherent.js
 * Provides plugins and utilities for using Coherent.js with Fastify
 */
 
import {
  renderWithTemplate,
  renderComponentFactory
} from '@coherent.js/core';
 
/**
 * Fastify plugin for Coherent.js
 * Automatically renders Coherent.js components and handles errors
 *
 * @param {Object} fastify - Fastify instance
 * @param {Object} options - Plugin options
 * @param {boolean} options.enablePerformanceMonitoring - Enable performance monitoring
 * @param {string} options.template - HTML template with {{content}} placeholder
 * @param {Function} done - Callback to signal plugin registration completion
 */
export function coherentFastify(fastify, options, done) {
  const {
    enablePerformanceMonitoring = false,
    template = '<!DOCTYPE html>\n{{content}}'
  } = options;
 
  // Add decorator to check if an object is a Coherent.js component
  fastify.decorateReply('isCoherentObject', (obj) => {
    if (!obj || typeof obj !== 'object' || Array.isArray(obj)) {
      return false;
    }
 
    const keys = Object.keys(obj);
    return keys.length === 1;
  });
 
  // Add decorator for rendering Coherent.js components
  fastify.decorateReply('coherent', function(component, renderOptions = {}) {
    const {
      enablePerformanceMonitoring: renderPerformanceMonitoring = enablePerformanceMonitoring,
      template: renderTemplate = template
    } = renderOptions;
 
    try {
      // Use shared rendering utility
      const finalHtml = renderWithTemplate(component, {
        enablePerformanceMonitoring: renderPerformanceMonitoring,
        template: renderTemplate
      });
 
      // Set content type and send HTML
      this.header('Content-Type', 'text/html; charset=utf-8');
      this.send(finalHtml);
    } catch (_error) {
      console.error('Coherent.js rendering _error:', _error);
      this.status(500).send({
        _error: 'Internal Server Error',
        message: _error.message
      });
    }
  });
 
  // Hook to automatically render Coherent.js objects
  fastify.addHook('onSend', async (request, reply, payload) => {
    // If payload is a Coherent.js object, render it
    if (reply.isCoherentObject(payload)) {
      try {
        // Use shared rendering utility
        const finalHtml = renderWithTemplate(payload, { enablePerformanceMonitoring, template });
 
        // Set content type and return HTML
        reply.header('Content-Type', 'text/html; charset=utf-8');
        return finalHtml;
      } catch (_error) {
        console.error('Coherent.js rendering _error:', _error);
        throw _error;
      }
    }
 
    // For non-Coherent.js data, return as-is
    return payload;
  });
 
  done();
}
 
/**
 * Create a Fastify route handler for Coherent.js components
 *
 * @param {Function} componentFactory - Function that returns a Coherent.js component
 * @param {Object} options - Handler options
 * @returns {Function} Fastify route handler
 */
export function createHandler(componentFactory, options = {}) {
  return async (request, reply) => {
    try {
      // Use shared rendering utility
      const finalHtml = await renderComponentFactory(
        componentFactory,
        [request, reply],
        options
      );
 
      // Send HTML response
      reply.header('Content-Type', 'text/html; charset=utf-8');
      return finalHtml;
    } catch (_error) {
      console.error('Coherent.js handler _error:', _error);
      throw _error;
    }
  };
}
 
/**
 * Setup Coherent.js with Fastify instance
 *
 * @param {Object} fastify - Fastify instance
 * @param {Object} options - Setup options
 */
export function setupCoherent(fastify, options = {}) {
  fastify.register(coherentFastify, options);
}
 
// Export plugin as default for Fastify's plugin system
export default coherentFastify;