@coherent.js/integrations 1.0.0-rc.1 → 1.0.0-rc.3
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coherent.js/integrations",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.3",
|
|
4
4
|
"description": "Framework integration adapters for Coherent.js: Express, Fastify, Koa, Next.js, Astro, Remix, SvelteKit.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -47,6 +47,9 @@
|
|
|
47
47
|
"bugs": {
|
|
48
48
|
"url": "https://github.com/Tomdrouv1/coherent.js/issues"
|
|
49
49
|
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"fastify-plugin": "^4.5.1"
|
|
52
|
+
},
|
|
50
53
|
"peerDependencies": {
|
|
51
54
|
"@remix-run/server-runtime": ">=2.0.0",
|
|
52
55
|
"@sveltejs/kit": ">=2.0.0",
|
|
@@ -56,7 +59,7 @@
|
|
|
56
59
|
"koa": ">=2.13.0 < 4.0.0",
|
|
57
60
|
"next": ">=13.0.0",
|
|
58
61
|
"react": ">=18.0.0",
|
|
59
|
-
"@coherent.js/core": "1.0.0-rc.
|
|
62
|
+
"@coherent.js/core": "1.0.0-rc.3"
|
|
60
63
|
},
|
|
61
64
|
"peerDependenciesMeta": {
|
|
62
65
|
"@remix-run/server-runtime": {
|
|
@@ -1,24 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Fastify integration for Coherent.js
|
|
3
|
-
* Provides plugins and utilities for using Coherent.js with Fastify
|
|
3
|
+
* Provides plugins and utilities for using Coherent.js with Fastify.
|
|
4
|
+
*
|
|
5
|
+
* The plugin must be wrapped with fastify-plugin (fp). Without fp, every
|
|
6
|
+
* `fastify.register(...)` boundary creates a fresh encapsulated context,
|
|
7
|
+
* and the `preSerialization` hook + `isCoherentObject` decorator only
|
|
8
|
+
* apply to routes registered INSIDE that context. The user's root-level
|
|
9
|
+
* routes would never see them, and responses would JSON-serialize the
|
|
10
|
+
* raw component object instead of rendering it.
|
|
4
11
|
*/
|
|
5
12
|
|
|
13
|
+
import fp from 'fastify-plugin';
|
|
6
14
|
import {
|
|
7
15
|
renderWithTemplate,
|
|
8
16
|
renderComponentFactory
|
|
9
17
|
} from '@coherent.js/core';
|
|
10
18
|
|
|
11
19
|
/**
|
|
12
|
-
* Fastify plugin
|
|
13
|
-
*
|
|
20
|
+
* Fastify plugin implementation. Not exported directly — use the fp-wrapped
|
|
21
|
+
* `coherentFastify` (or its alias `setupCoherent`) instead.
|
|
14
22
|
*
|
|
15
23
|
* @param {Object} fastify - Fastify instance
|
|
16
24
|
* @param {Object} options - Plugin options
|
|
17
|
-
* @param {boolean} options.enablePerformanceMonitoring - Enable performance monitoring
|
|
18
|
-
* @param {string} options.template - HTML template with {{content}} placeholder
|
|
25
|
+
* @param {boolean} [options.enablePerformanceMonitoring] - Enable performance monitoring
|
|
26
|
+
* @param {string} [options.template] - HTML template with {{content}} placeholder
|
|
19
27
|
* @param {Function} done - Callback to signal plugin registration completion
|
|
20
28
|
*/
|
|
21
|
-
|
|
29
|
+
function coherentFastifyImpl(fastify, options = {}, done) {
|
|
22
30
|
const {
|
|
23
31
|
enablePerformanceMonitoring = false,
|
|
24
32
|
template = '<!DOCTYPE html>\n{{content}}'
|
|
@@ -29,12 +37,11 @@ export function coherentFastify(fastify, options, done) {
|
|
|
29
37
|
if (!obj || typeof obj !== 'object' || Array.isArray(obj)) {
|
|
30
38
|
return false;
|
|
31
39
|
}
|
|
32
|
-
|
|
33
40
|
const keys = Object.keys(obj);
|
|
34
41
|
return keys.length === 1;
|
|
35
42
|
});
|
|
36
43
|
|
|
37
|
-
// Add decorator for rendering
|
|
44
|
+
// Add decorator for explicit rendering: reply.coherent(component, opts?)
|
|
38
45
|
fastify.decorateReply('coherent', function(component, renderOptions = {}) {
|
|
39
46
|
const {
|
|
40
47
|
enablePerformanceMonitoring: renderPerformanceMonitoring = enablePerformanceMonitoring,
|
|
@@ -42,13 +49,10 @@ export function coherentFastify(fastify, options, done) {
|
|
|
42
49
|
} = renderOptions;
|
|
43
50
|
|
|
44
51
|
try {
|
|
45
|
-
// Use shared rendering utility
|
|
46
52
|
const finalHtml = renderWithTemplate(component, {
|
|
47
53
|
enablePerformanceMonitoring: renderPerformanceMonitoring,
|
|
48
54
|
template: renderTemplate
|
|
49
55
|
});
|
|
50
|
-
|
|
51
|
-
// Set content type and send HTML
|
|
52
56
|
this.header('Content-Type', 'text/html; charset=utf-8');
|
|
53
57
|
this.send(finalHtml);
|
|
54
58
|
} catch (_error) {
|
|
@@ -60,24 +64,21 @@ export function coherentFastify(fastify, options, done) {
|
|
|
60
64
|
}
|
|
61
65
|
});
|
|
62
66
|
|
|
63
|
-
//
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
67
|
+
// Auto-render: if a handler returns a Coherent.js component object,
|
|
68
|
+
// intercept before serialization and replace the payload with HTML.
|
|
69
|
+
//
|
|
70
|
+
// - `onSend` runs after JSON serialization (payload is already a string),
|
|
71
|
+
// so the component object would never be detected there.
|
|
72
|
+
// - `preSerialization` runs before serialization. We render to HTML and
|
|
73
|
+
// install an identity serializer for this reply, so Fastify doesn't
|
|
74
|
+
// JSON-stringify the HTML string we just produced.
|
|
75
|
+
fastify.addHook('preSerialization', async (request, reply, payload) => {
|
|
76
|
+
if (reply.isCoherentObject?.(payload)) {
|
|
77
|
+
const finalHtml = renderWithTemplate(payload, { enablePerformanceMonitoring, template });
|
|
78
|
+
reply.header('Content-Type', 'text/html; charset=utf-8');
|
|
79
|
+
reply.serializer((p) => p);
|
|
80
|
+
return finalHtml;
|
|
78
81
|
}
|
|
79
|
-
|
|
80
|
-
// For non-Coherent.js data, return as-is
|
|
81
82
|
return payload;
|
|
82
83
|
});
|
|
83
84
|
|
|
@@ -85,7 +86,27 @@ export function coherentFastify(fastify, options, done) {
|
|
|
85
86
|
}
|
|
86
87
|
|
|
87
88
|
/**
|
|
88
|
-
*
|
|
89
|
+
* Fastify plugin for Coherent.js — wrapped with fastify-plugin so decorators
|
|
90
|
+
* and hooks apply to the parent (root) context. Register at the top of your
|
|
91
|
+
* app, then define routes that return Coherent.js component objects:
|
|
92
|
+
*
|
|
93
|
+
* await fastify.register(coherentFastify, { template: APP_HTML_TEMPLATE });
|
|
94
|
+
* fastify.get('/', async () => HomePage({}));
|
|
95
|
+
*/
|
|
96
|
+
export const coherentFastify = fp(coherentFastifyImpl, {
|
|
97
|
+
name: 'coherent-fastify',
|
|
98
|
+
fastify: '>=4.0.0'
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Alias for `coherentFastify`. Preserved for backward compatibility with
|
|
103
|
+
* scaffolds and examples that use `setupCoherent`. Behaves identically:
|
|
104
|
+
* `await fastify.register(setupCoherent, options)`.
|
|
105
|
+
*/
|
|
106
|
+
export const setupCoherent = coherentFastify;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Create a Fastify route handler for Coherent.js components.
|
|
89
110
|
*
|
|
90
111
|
* @param {Function} componentFactory - Function that returns a Coherent.js component
|
|
91
112
|
* @param {Object} options - Handler options
|
|
@@ -94,14 +115,11 @@ export function coherentFastify(fastify, options, done) {
|
|
|
94
115
|
export function createHandler(componentFactory, options = {}) {
|
|
95
116
|
return async (request, reply) => {
|
|
96
117
|
try {
|
|
97
|
-
// Use shared rendering utility
|
|
98
118
|
const finalHtml = await renderComponentFactory(
|
|
99
119
|
componentFactory,
|
|
100
120
|
[request, reply],
|
|
101
121
|
options
|
|
102
122
|
);
|
|
103
|
-
|
|
104
|
-
// Send HTML response
|
|
105
123
|
reply.header('Content-Type', 'text/html; charset=utf-8');
|
|
106
124
|
return finalHtml;
|
|
107
125
|
} catch (_error) {
|
|
@@ -111,15 +129,5 @@ export function createHandler(componentFactory, options = {}) {
|
|
|
111
129
|
};
|
|
112
130
|
}
|
|
113
131
|
|
|
114
|
-
|
|
115
|
-
* Setup Coherent.js with Fastify instance
|
|
116
|
-
*
|
|
117
|
-
* @param {Object} fastify - Fastify instance
|
|
118
|
-
* @param {Object} options - Setup options
|
|
119
|
-
*/
|
|
120
|
-
export function setupCoherent(fastify, options = {}) {
|
|
121
|
-
fastify.register(coherentFastify, options);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Export plugin as default for Fastify's plugin system
|
|
132
|
+
// Default export = the plugin, for `fastify.register(import('@coherent.js/integrations/fastify'))`.
|
|
125
133
|
export default coherentFastify;
|
package/src/koa/coherent-koa.js
CHANGED
|
@@ -79,14 +79,13 @@ export function createHandler(componentFactory, options = {}) {
|
|
|
79
79
|
* @param {Object} options - Setup options
|
|
80
80
|
*/
|
|
81
81
|
export function setupCoherent(app, options = {}) {
|
|
82
|
-
const {
|
|
83
|
-
useMiddleware = true,
|
|
84
|
-
enablePerformanceMonitoring = false
|
|
85
|
-
} = options;
|
|
82
|
+
const { useMiddleware = true, ...middlewareOptions } = options;
|
|
86
83
|
|
|
87
|
-
// Use middleware for automatic rendering
|
|
84
|
+
// Use middleware for automatic rendering. Forward everything except the
|
|
85
|
+
// setup-only flag so callers can supply `template`, `enablePerformanceMonitoring`,
|
|
86
|
+
// and any future middleware options.
|
|
88
87
|
if (useMiddleware) {
|
|
89
|
-
app.use(coherentKoaMiddleware(
|
|
88
|
+
app.use(coherentKoaMiddleware(middlewareOptions));
|
|
90
89
|
}
|
|
91
90
|
}
|
|
92
91
|
|