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 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | 7x 7x 9x 3x 3x 3x 3x 9x 8x 1x 1x 1x 1x 1x 5x 5x 5x | /**
* Koa.js integration for Coherent.js
* Provides middleware and utilities for using Coherent.js with Koa
*/
import {
importPeerDependency,
renderWithTemplate,
renderComponentFactory,
isCoherentComponent
} from '@coherent.js/core';
/**
* Coherent.js Koa middleware.
*
* Adds `ctx.coherent(component, renderOptions?)`, which renders a Coherent.js
* component (wrapped in `template`) into `ctx.body` as `text/html`. Rendering
* errors are thrown, so they reach the app's error-handling middleware.
*
* With `autoRender: true` it additionally renders any `ctx.body` that looks
* like a component once downstream middleware has finished. That detection
* is a heuristic -- every single-key object qualifies, so
* `ctx.body = { ok: true }` would be rendered as `<ok>` instead of serialized
* as JSON. It is off by default; only enable it for apps that never respond
* with single-key JSON objects.
*
* @param {Object} options - Configuration options
* @param {boolean} [options.enablePerformanceMonitoring=false] - Enable performance monitoring
* @param {string} [options.template] - HTML template with {{content}} placeholder
* @param {boolean} [options.autoRender=false] - Render component-shaped `ctx.body` values
* @returns {Function} Koa middleware function
*/
export function coherentKoaMiddleware(options = {}) {
const {
enablePerformanceMonitoring = false,
template = '<!DOCTYPE html>\n{{content}}',
autoRender = false
} = options;
return async (ctx, next) => {
// Explicit rendering: ctx.coherent(component, { template?, enablePerformanceMonitoring? })
ctx.coherent = (component, renderOptions = {}) => {
const finalHtml = renderWithTemplate(component, {
enablePerformanceMonitoring: renderOptions.enablePerformanceMonitoring ?? enablePerformanceMonitoring,
template: renderOptions.template ?? template
});
ctx.type = 'html';
ctx.body = finalHtml;
return finalHtml;
};
await next();
// Opt-in: if the response body looks like a Coherent.js object, render it
if (autoRender && isCoherentComponent(ctx.body)) {
try {
// Use shared rendering utility
const finalHtml = renderWithTemplate(ctx.body, { enablePerformanceMonitoring, template });
// Set content type and body
ctx.type = 'text/html';
ctx.body = finalHtml;
} catch (_error) {
console.error('Coherent.js rendering error:', _error);
throw _error;
}
}
};
}
/**
* Create a Koa route handler for Coherent.js components
*
* @param {Function} componentFactory - Function that returns a Coherent.js component
* @param {Object} options - Handler options
* @returns {Function} Koa route handler
*/
export function createHandler(componentFactory, options = {}) {
return async (ctx, next) => {
try {
// Use shared rendering utility
const finalHtml = await renderComponentFactory(
componentFactory,
[ctx, next],
options
);
// Set response
ctx.type = 'text/html';
ctx.body = finalHtml;
} catch (_error) {
console.error('Coherent.js handler error:', _error);
throw _error;
}
};
}
/**
* Setup Coherent.js with Koa app
*
* Installs {@link coherentKoaMiddleware}, so downstream middleware can call
* `ctx.coherent(component)`. Every option except `useMiddleware` is forwarded
* to the middleware, including `template` and `autoRender`.
*
* @param {Object} app - Koa app instance
* @param {Object} options - Setup options
* @param {boolean} [options.useMiddleware=true] - Install coherentKoaMiddleware
*/
export function setupCoherent(app, options = {}) {
const { useMiddleware = true, ...middlewareOptions } = options;
// Use middleware for automatic rendering. Forward everything except the
// setup-only flag so callers can supply `template`, `enablePerformanceMonitoring`,
// and any future middleware options.
Eif (useMiddleware) {
app.use(coherentKoaMiddleware(middlewareOptions));
}
}
/**
* Create Koa integration with dependency checking
* This function ensures Koa is available before setting up the integration
*
* @param {Object} options - Setup options
* @returns {Promise<Function>} - Function to setup Koa integration
*/
export async function createKoaIntegration(options = {}) {
try {
// Verify Koa is available
await importPeerDependency('koa', 'Koa.js');
return function(app) {
if (!app || typeof app.use !== 'function') {
throw new Error('Invalid Koa app instance provided');
}
setupCoherent(app, options);
return app;
};
} catch (_error) {
throw _error;
}
}
// Export all utilities
export default {
coherentKoaMiddleware,
createHandler,
setupCoherent,
createKoaIntegration
};
|