@coherent.js/express 1.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Thomas Drouvin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # @coherent.js/express
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@coherent.js/express.svg)](https://www.npmjs.com/package/@coherent.js/express)
4
+ [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](../../LICENSE)
5
+ [![Node >= 20](https://img.shields.io/badge/node-%3E%3D20-brightgreen)](https://nodejs.org)
6
+
7
+ Express adapter for Coherent.js.
8
+
9
+ - ESM-only, Node 20+
10
+ - Works with `express@4.x`
11
+ - Designed to pair with `@coherent.js/core`
12
+
13
+ For a high-level overview and repository-wide instructions, see the root README: ../../README.md
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ pnpm add @coherent.js/express express @coherent.js/core
19
+ ```
20
+
21
+ Peer dependencies:
22
+ - `express` >= 4.18 < 6
23
+ - `@coherent.js/core`
24
+
25
+ ## Quick start
26
+
27
+ You can use `@coherent.js/core` rendering inside Express handlers.
28
+
29
+ JavaScript (ESM):
30
+ ```js
31
+ import express from 'express';
32
+ import { renderToString } from '@coherent.js/core';
33
+
34
+ const app = express();
35
+
36
+ app.get('/', async (_req, res) => {
37
+ const html = await renderToString({ div: { text: 'Hello from Express + Coherent' } });
38
+ res.type('html').send(html);
39
+ });
40
+
41
+ app.listen(3000, () => console.log('http://localhost:3000'));
42
+ ```
43
+
44
+ TypeScript:
45
+ ```ts
46
+ import express, { Request, Response } from 'express';
47
+ import { renderToString } from '@coherent.js/core';
48
+
49
+ const app = express();
50
+
51
+ app.get('/', async (_req: Request, res: Response) => {
52
+ const html = await renderToString({ div: { text: 'Hello TS' } });
53
+ res.type('html').send(html);
54
+ });
55
+
56
+ app.listen(3000);
57
+ ```
58
+
59
+ ## Development
60
+
61
+ ```bash
62
+ pnpm --filter @coherent.js/express run test
63
+ pnpm --filter @coherent.js/express run test:watch
64
+ pnpm --filter @coherent.js/express run typecheck
65
+ pnpm --filter @coherent.js/express run build
66
+ ```
67
+
68
+ ## License
69
+
70
+ MIT © Coherent.js Team
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Coherent.js Express middleware
3
+ * Automatically renders Coherent.js components and handles errors
4
+ *
5
+ * @param {Object} options - Configuration options
6
+ * @param {boolean} options.enablePerformanceMonitoring - Enable performance monitoring
7
+ * @param {string} options.template - HTML template with {{content}} placeholder
8
+ * @returns {Function} Express middleware function
9
+ */
10
+ export function coherentMiddleware(options?: {
11
+ enablePerformanceMonitoring: boolean;
12
+ template: string;
13
+ }): Function;
14
+ /**
15
+ * Create an Express route handler for Coherent.js components
16
+ *
17
+ * @param {Function} componentFactory - Function that returns a Coherent.js component
18
+ * @param {Object} options - Handler options
19
+ * @returns {Function} Express route handler
20
+ */
21
+ export function createCoherentHandler(componentFactory: Function, options?: Object): Function;
22
+ /**
23
+ * Enhanced Express engine for Coherent.js views
24
+ *
25
+ * @param {string} filePath - Path to view file (not used in Coherent.js)
26
+ * @param {Object} options - View options containing Coherent.js component
27
+ * @param {Function} callback - Callback function
28
+ */
29
+ export function enhancedExpressEngine(filePath: string, options: Object, callback: Function): void;
30
+ /**
31
+ * Setup Coherent.js with Express app
32
+ *
33
+ * @param {Object} app - Express app instance
34
+ * @param {Object} options - Setup options
35
+ */
36
+ export function setupCoherentExpress(app: Object, options?: Object): void;
37
+ /**
38
+ * Create Express integration with dependency checking
39
+ * This function ensures Express is available before setting up the integration
40
+ *
41
+ * @param {Object} options - Setup options
42
+ * @returns {Promise<Function>} - Function to setup Express integration
43
+ */
44
+ export function createExpressIntegration(options?: Object): Promise<Function>;
45
+ declare namespace _default {
46
+ export { coherentMiddleware };
47
+ export { createCoherentHandler };
48
+ export { enhancedExpressEngine };
49
+ export { setupCoherentExpress };
50
+ export { createExpressIntegration };
51
+ }
52
+ export default _default;
53
+ //# sourceMappingURL=coherent-express.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coherent-express.d.ts","sourceRoot":"","sources":["../../../../src/express/coherent-express.js"],"names":[],"mappings":"AASA;;;;;;;;GAQG;AACH,6CAJG;IAAyB,2BAA2B,EAA5C,OAAO;IACS,QAAQ,EAAxB,MAAM;CACd,YA6CF;AAkBD;;;;;;GAMG;AACH,4EAHW,MAAM,YAyChB;AAED;;;;;;GAMG;AACH,gDAJW,MAAM,WACN,MAAM,4BAWhB;AAED;;;;;GAKG;AACH,0CAHW,MAAM,YACN,MAAM,QAoBhB;AAED;;;;;;GAMG;AACH,mDAHW,MAAM,GACJ,OAAO,UAAU,CAkB7B"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Enhanced Express.js integration for Coherent.js
3
+ * Provides middleware and utilities for using Coherent.js with Express
4
+ */
5
+ import { renderToString, renderHTML } from '../rendering/html-renderer.js';
6
+ import { performanceMonitor } from '../performance/monitor.js';
7
+ import { importPeerDependency } from '../utils/dependency-utils.js';
8
+ /**
9
+ * Coherent.js Express middleware
10
+ * Automatically renders Coherent.js components and handles errors
11
+ *
12
+ * @param {Object} options - Configuration options
13
+ * @param {boolean} options.enablePerformanceMonitoring - Enable performance monitoring
14
+ * @param {string} options.template - HTML template with {{content}} placeholder
15
+ * @returns {Function} Express middleware function
16
+ */
17
+ export function coherentMiddleware(options = {}) {
18
+ const { enablePerformanceMonitoring = false, template = '<!DOCTYPE html>\n{{content}}' } = options;
19
+ return (req, res, next) => {
20
+ // Store original send method
21
+ const originalSend = res.send;
22
+ // Override send method to handle Coherent.js objects
23
+ res.send = function (data) {
24
+ // If data is a Coherent.js object (plain object with a single key), render it
25
+ if (isCoherentObject(data)) {
26
+ try {
27
+ let html;
28
+ if (enablePerformanceMonitoring) {
29
+ const renderId = performanceMonitor.startRender();
30
+ html = renderToString(data);
31
+ performanceMonitor.endRender(renderId);
32
+ }
33
+ else {
34
+ html = renderToString(data);
35
+ }
36
+ // Apply template
37
+ const finalHtml = template.replace('{{content}}', html);
38
+ // Set content type and send HTML
39
+ res.set('Content-Type', 'text/html');
40
+ return originalSend.call(this, finalHtml);
41
+ }
42
+ catch (error) {
43
+ console.error('Coherent.js rendering error:', error);
44
+ return next(error);
45
+ }
46
+ }
47
+ // For non-Coherent.js data, use original send method
48
+ return originalSend.call(this, data);
49
+ };
50
+ next();
51
+ };
52
+ }
53
+ /**
54
+ * Check if an object is a Coherent.js component object
55
+ * A Coherent.js component is a plain object with a single key
56
+ *
57
+ * @param {any} obj - Object to check
58
+ * @returns {boolean} True if object is a Coherent.js component
59
+ */
60
+ function isCoherentObject(obj) {
61
+ if (!obj || typeof obj !== 'object' || Array.isArray(obj)) {
62
+ return false;
63
+ }
64
+ const keys = Object.keys(obj);
65
+ return keys.length === 1;
66
+ }
67
+ /**
68
+ * Create an Express route handler for Coherent.js components
69
+ *
70
+ * @param {Function} componentFactory - Function that returns a Coherent.js component
71
+ * @param {Object} options - Handler options
72
+ * @returns {Function} Express route handler
73
+ */
74
+ export function createCoherentHandler(componentFactory, options = {}) {
75
+ const { enablePerformanceMonitoring = false, template = '<!DOCTYPE html>\n{{content}}' } = options;
76
+ return async (req, res, next) => {
77
+ try {
78
+ // Create component with request data
79
+ const component = await Promise.resolve(componentFactory(req, res, next));
80
+ if (!component) {
81
+ return next(new Error('Component factory returned null/undefined'));
82
+ }
83
+ // Render component
84
+ let html;
85
+ if (enablePerformanceMonitoring) {
86
+ const renderId = performanceMonitor.startRender();
87
+ html = renderToString(component);
88
+ performanceMonitor.endRender(renderId);
89
+ }
90
+ else {
91
+ html = renderToString(component);
92
+ }
93
+ // Apply template
94
+ const finalHtml = template.replace('{{content}}', html);
95
+ // Send HTML response
96
+ res.set('Content-Type', 'text/html');
97
+ res.send(finalHtml);
98
+ }
99
+ catch (error) {
100
+ console.error('Coherent.js handler error:', error);
101
+ next(error);
102
+ }
103
+ };
104
+ }
105
+ /**
106
+ * Enhanced Express engine for Coherent.js views
107
+ *
108
+ * @param {string} filePath - Path to view file (not used in Coherent.js)
109
+ * @param {Object} options - View options containing Coherent.js component
110
+ * @param {Function} callback - Callback function
111
+ */
112
+ export function enhancedExpressEngine(filePath, options, callback) {
113
+ try {
114
+ // Render Coherent.js component from options
115
+ const html = renderHTML(options);
116
+ callback(null, html);
117
+ }
118
+ catch (error) {
119
+ callback(error);
120
+ }
121
+ }
122
+ /**
123
+ * Setup Coherent.js with Express app
124
+ *
125
+ * @param {Object} app - Express app instance
126
+ * @param {Object} options - Setup options
127
+ */
128
+ export function setupCoherentExpress(app, options = {}) {
129
+ const { useMiddleware = true, useEngine = true, engineName = 'coherent', enablePerformanceMonitoring = false } = options;
130
+ // Register enhanced engine
131
+ if (useEngine) {
132
+ app.engine(engineName, enhancedExpressEngine);
133
+ app.set('view engine', engineName);
134
+ }
135
+ // Use middleware for automatic rendering
136
+ if (useMiddleware) {
137
+ app.use(coherentMiddleware({ enablePerformanceMonitoring }));
138
+ }
139
+ }
140
+ /**
141
+ * Create Express integration with dependency checking
142
+ * This function ensures Express is available before setting up the integration
143
+ *
144
+ * @param {Object} options - Setup options
145
+ * @returns {Promise<Function>} - Function to setup Express integration
146
+ */
147
+ export async function createExpressIntegration(options = {}) {
148
+ try {
149
+ // Verify Express is available
150
+ await importPeerDependency('express', 'Express.js');
151
+ return function (app) {
152
+ if (!app || typeof app.use !== 'function') {
153
+ throw new Error('Invalid Express app instance provided');
154
+ }
155
+ setupCoherentExpress(app, options);
156
+ return app;
157
+ };
158
+ }
159
+ catch (error) {
160
+ throw error;
161
+ }
162
+ }
163
+ // Export all utilities
164
+ export default {
165
+ coherentMiddleware,
166
+ createCoherentHandler,
167
+ enhancedExpressEngine,
168
+ setupCoherentExpress,
169
+ createExpressIntegration
170
+ };
171
+ //# sourceMappingURL=coherent-express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coherent-express.js","sourceRoot":"","sources":["../../../../src/express/coherent-express.js"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export function expressEngine(): (filePath: any, options: any, callback: any) => void;
2
+ export function setupCoherent(app: any): void;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/express/index.js"],"names":[],"mappings":"AAGA,kCACY,aAAQ,EAAE,YAAO,EAAE,aAAQ,UAStC;AAGD,8CAGC"}
@@ -0,0 +1,20 @@
1
+ // src/express/index.js
2
+ import { renderHTML } from '../rendering/html-renderer.js';
3
+ export function expressEngine() {
4
+ return (filePath, options, callback) => {
5
+ try {
6
+ // options contains the Coherent object structure
7
+ const html = renderHTML(options);
8
+ callback(null, html);
9
+ }
10
+ catch (error) {
11
+ callback(error);
12
+ }
13
+ };
14
+ }
15
+ // Helper for Express apps
16
+ export function setupCoherent(app) {
17
+ app.engine('coherent', expressEngine());
18
+ app.set('view engine', 'coherent');
19
+ }
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/express/index.js"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,MAAM,UAAU,aAAa;IACzB,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;QACnC,IAAI,CAAC;YACD,iDAAiD;YACjD,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;YACjC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,QAAQ,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACL,CAAC,CAAC;AACN,CAAC;AAED,0BAA0B;AAC1B,MAAM,UAAU,aAAa,CAAC,GAAG;IAC7B,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,aAAa,EAAE,CAAC,CAAC;IACxC,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;AACvC,CAAC"}