@coherent.js/fastify 1.0.0-beta.2 → 1.0.0-beta.5
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/README.md +18 -0
- package/dist/fastify/coherent-fastify.js +10 -10
- package/dist/index.cjs +10 -120
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +10 -110
- package/dist/index.js.map +4 -4
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -22,6 +22,24 @@ Peer dependencies:
|
|
|
22
22
|
- `fastify` >= 4 < 6
|
|
23
23
|
- `@coherent.js/core`
|
|
24
24
|
|
|
25
|
+
|
|
26
|
+
## Exports
|
|
27
|
+
|
|
28
|
+
Fastify adapter for Coherent.js
|
|
29
|
+
|
|
30
|
+
### Modular Imports (Tree-Shakable)
|
|
31
|
+
|
|
32
|
+
- Fastify integration: `@coherent.js/fastify`
|
|
33
|
+
- Handler creation: `@coherent.js/fastify`
|
|
34
|
+
|
|
35
|
+
### Example Usage
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
import { setupCoherent } from '@coherent.js/fastify';
|
|
39
|
+
import { createHandler } from '@coherent.js/fastify';
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
> **Note**: All exports are tree-shakable. Import only what you need for optimal bundle size.
|
|
25
43
|
## Quick start
|
|
26
44
|
|
|
27
45
|
You can use `@coherent.js/core` rendering inside Fastify route handlers.
|
|
@@ -43,11 +43,11 @@ export function coherentFastify(fastify, options, done) {
|
|
|
43
43
|
this.header('Content-Type', 'text/html; charset=utf-8');
|
|
44
44
|
this.send(finalHtml);
|
|
45
45
|
}
|
|
46
|
-
catch (
|
|
47
|
-
console.
|
|
46
|
+
catch (_error) {
|
|
47
|
+
console._error('Coherent.js rendering _error:', _error);
|
|
48
48
|
this.status(500).send({
|
|
49
|
-
|
|
50
|
-
message:
|
|
49
|
+
_error: 'Internal Server Error',
|
|
50
|
+
message: _error.message
|
|
51
51
|
});
|
|
52
52
|
}
|
|
53
53
|
});
|
|
@@ -71,9 +71,9 @@ export function coherentFastify(fastify, options, done) {
|
|
|
71
71
|
reply.header('Content-Type', 'text/html; charset=utf-8');
|
|
72
72
|
return finalHtml;
|
|
73
73
|
}
|
|
74
|
-
catch (
|
|
75
|
-
console.
|
|
76
|
-
throw
|
|
74
|
+
catch (_error) {
|
|
75
|
+
console._error('Coherent.js rendering _error:', _error);
|
|
76
|
+
throw _error;
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
// For non-Coherent.js data, return as-is
|
|
@@ -113,9 +113,9 @@ export function createCoherentFastifyHandler(componentFactory, options = {}) {
|
|
|
113
113
|
reply.header('Content-Type', 'text/html; charset=utf-8');
|
|
114
114
|
return finalHtml;
|
|
115
115
|
}
|
|
116
|
-
catch (
|
|
117
|
-
console.
|
|
118
|
-
throw
|
|
116
|
+
catch (_error) {
|
|
117
|
+
console._error('Coherent.js handler _error:', _error);
|
|
118
|
+
throw _error;
|
|
119
119
|
}
|
|
120
120
|
};
|
|
121
121
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
|
|
30
20
|
// src/coherent-fastify.js
|
|
@@ -38,9 +28,9 @@ __export(coherent_fastify_exports, {
|
|
|
38
28
|
module.exports = __toCommonJS(coherent_fastify_exports);
|
|
39
29
|
|
|
40
30
|
// ../core/src/core/object-utils.js
|
|
41
|
-
function validateComponent(component,
|
|
31
|
+
function validateComponent(component, path = "root") {
|
|
42
32
|
if (component === null || component === void 0) {
|
|
43
|
-
throw new Error(`Invalid component at ${
|
|
33
|
+
throw new Error(`Invalid component at ${path}: null or undefined`);
|
|
44
34
|
}
|
|
45
35
|
if (["string", "number", "boolean"].includes(typeof component)) {
|
|
46
36
|
return true;
|
|
@@ -50,31 +40,31 @@ function validateComponent(component, path2 = "root") {
|
|
|
50
40
|
}
|
|
51
41
|
if (Array.isArray(component)) {
|
|
52
42
|
component.forEach((child, index) => {
|
|
53
|
-
validateComponent(child, `${
|
|
43
|
+
validateComponent(child, `${path}[${index}]`);
|
|
54
44
|
});
|
|
55
45
|
return true;
|
|
56
46
|
}
|
|
57
47
|
if (typeof component === "object") {
|
|
58
48
|
const keys = Object.keys(component);
|
|
59
49
|
if (keys.length === 0) {
|
|
60
|
-
throw new Error(`Empty object at ${
|
|
50
|
+
throw new Error(`Empty object at ${path}`);
|
|
61
51
|
}
|
|
62
52
|
keys.forEach((key) => {
|
|
63
53
|
const value = component[key];
|
|
64
54
|
if (!/^[a-zA-Z][a-zA-Z0-9-]*$/.test(key) && key !== "text") {
|
|
65
|
-
console.warn(`Potentially invalid tag name at ${
|
|
55
|
+
console.warn(`Potentially invalid tag name at ${path}: ${key}`);
|
|
66
56
|
}
|
|
67
57
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
68
58
|
if (value.children) {
|
|
69
|
-
validateComponent(value.children, `${
|
|
59
|
+
validateComponent(value.children, `${path}.${key}.children`);
|
|
70
60
|
}
|
|
71
61
|
} else if (value && typeof value !== "string" && typeof value !== "number" && typeof value !== "function") {
|
|
72
|
-
throw new Error(`Invalid value type at ${
|
|
62
|
+
throw new Error(`Invalid value type at ${path}.${key}: ${typeof value}`);
|
|
73
63
|
}
|
|
74
64
|
});
|
|
75
65
|
return true;
|
|
76
66
|
}
|
|
77
|
-
throw new Error(`Invalid component type at ${
|
|
67
|
+
throw new Error(`Invalid component type at ${path}: ${typeof component}`);
|
|
78
68
|
}
|
|
79
69
|
function isCoherentObject(obj) {
|
|
80
70
|
if (!obj || typeof obj !== "object" || Array.isArray(obj)) {
|
|
@@ -156,6 +146,7 @@ function createPerformanceMonitor(options = {}) {
|
|
|
156
146
|
},
|
|
157
147
|
alerts: {
|
|
158
148
|
enabled: true,
|
|
149
|
+
debounceMs: 5e3,
|
|
159
150
|
rules: []
|
|
160
151
|
},
|
|
161
152
|
resources: {
|
|
@@ -317,7 +308,7 @@ function createPerformanceMonitor(options = {}) {
|
|
|
317
308
|
const alertKey = `${rule.metric}-${rule.condition}-${rule.threshold}`;
|
|
318
309
|
const lastTriggered = alertState.triggered.get(alertKey);
|
|
319
310
|
const now = Date.now();
|
|
320
|
-
if (!lastTriggered || now - lastTriggered >
|
|
311
|
+
if (!lastTriggered || now - lastTriggered > opts.alerts.debounceMs) {
|
|
321
312
|
alertState.triggered.set(alertKey, now);
|
|
322
313
|
alertState.history.push({
|
|
323
314
|
rule,
|
|
@@ -1299,107 +1290,6 @@ function createCacheManager(options = {}) {
|
|
|
1299
1290
|
}
|
|
1300
1291
|
var cacheManager = createCacheManager();
|
|
1301
1292
|
|
|
1302
|
-
// ../core/src/rendering/css-manager.js
|
|
1303
|
-
var import_promises = __toESM(require("node:fs/promises"), 1);
|
|
1304
|
-
var import_node_path = __toESM(require("node:path"), 1);
|
|
1305
|
-
var CSSManager = class {
|
|
1306
|
-
constructor(options = {}) {
|
|
1307
|
-
this.options = {
|
|
1308
|
-
basePath: process.cwd(),
|
|
1309
|
-
minify: false,
|
|
1310
|
-
cache: true,
|
|
1311
|
-
autoprefixer: false,
|
|
1312
|
-
...options
|
|
1313
|
-
};
|
|
1314
|
-
this.cache = /* @__PURE__ */ new Map();
|
|
1315
|
-
this.loadedFiles = /* @__PURE__ */ new Set();
|
|
1316
|
-
}
|
|
1317
|
-
/**
|
|
1318
|
-
* Load CSS file content
|
|
1319
|
-
*/
|
|
1320
|
-
async loadCSSFile(filePath) {
|
|
1321
|
-
const fullPath = import_node_path.default.resolve(this.options.basePath, filePath);
|
|
1322
|
-
const cacheKey = fullPath;
|
|
1323
|
-
if (this.options.cache && this.cache.has(cacheKey)) {
|
|
1324
|
-
return this.cache.get(cacheKey);
|
|
1325
|
-
}
|
|
1326
|
-
try {
|
|
1327
|
-
let content = await import_promises.default.readFile(fullPath, "utf8");
|
|
1328
|
-
if (this.options.minify) {
|
|
1329
|
-
content = this.minifyCSS(content);
|
|
1330
|
-
}
|
|
1331
|
-
if (this.options.cache) {
|
|
1332
|
-
this.cache.set(cacheKey, content);
|
|
1333
|
-
}
|
|
1334
|
-
this.loadedFiles.add(filePath);
|
|
1335
|
-
return content;
|
|
1336
|
-
} catch (_error) {
|
|
1337
|
-
console.warn(`Failed to load CSS file: ${filePath}`, _error.message);
|
|
1338
|
-
return "";
|
|
1339
|
-
}
|
|
1340
|
-
}
|
|
1341
|
-
/**
|
|
1342
|
-
* Load multiple CSS files
|
|
1343
|
-
*/
|
|
1344
|
-
async loadCSSFiles(filePaths) {
|
|
1345
|
-
if (!Array.isArray(filePaths)) {
|
|
1346
|
-
filePaths = [filePaths];
|
|
1347
|
-
}
|
|
1348
|
-
const cssContents = await Promise.all(
|
|
1349
|
-
filePaths.map((filePath) => this.loadCSSFile(filePath))
|
|
1350
|
-
);
|
|
1351
|
-
return cssContents.join("\n");
|
|
1352
|
-
}
|
|
1353
|
-
/**
|
|
1354
|
-
* Generate CSS link tags for external files
|
|
1355
|
-
*/
|
|
1356
|
-
generateCSSLinks(filePaths, baseUrl = "/") {
|
|
1357
|
-
if (!Array.isArray(filePaths)) {
|
|
1358
|
-
filePaths = [filePaths];
|
|
1359
|
-
}
|
|
1360
|
-
return filePaths.map((filePath) => {
|
|
1361
|
-
const href = filePath.startsWith("http") ? filePath : `${baseUrl}${filePath}`.replace(/\/+/g, "/");
|
|
1362
|
-
return `<link rel="stylesheet" href="${this.escapeHtml(href)}" />`;
|
|
1363
|
-
}).join("\n");
|
|
1364
|
-
}
|
|
1365
|
-
/**
|
|
1366
|
-
* Generate inline style tag with CSS content
|
|
1367
|
-
*/
|
|
1368
|
-
generateInlineStyles(cssContent) {
|
|
1369
|
-
if (!cssContent) return "";
|
|
1370
|
-
return `<style type="text/css">
|
|
1371
|
-
${cssContent}
|
|
1372
|
-
</style>`;
|
|
1373
|
-
}
|
|
1374
|
-
/**
|
|
1375
|
-
* Basic CSS minification
|
|
1376
|
-
*/
|
|
1377
|
-
minifyCSS(css) {
|
|
1378
|
-
return css.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\s+/g, " ").replace(/;\s*}/g, "}").replace(/{\s+/g, "{").replace(/;\s+/g, ";").trim();
|
|
1379
|
-
}
|
|
1380
|
-
/**
|
|
1381
|
-
* Escape HTML entities
|
|
1382
|
-
*/
|
|
1383
|
-
escapeHtml(text) {
|
|
1384
|
-
const div = { textContent: text };
|
|
1385
|
-
return div.innerHTML || text;
|
|
1386
|
-
}
|
|
1387
|
-
/**
|
|
1388
|
-
* Clear cache
|
|
1389
|
-
*/
|
|
1390
|
-
clearCache() {
|
|
1391
|
-
this.cache.clear();
|
|
1392
|
-
this.loadedFiles.clear();
|
|
1393
|
-
}
|
|
1394
|
-
/**
|
|
1395
|
-
* Get loaded file list
|
|
1396
|
-
*/
|
|
1397
|
-
getLoadedFiles() {
|
|
1398
|
-
return Array.from(this.loadedFiles);
|
|
1399
|
-
}
|
|
1400
|
-
};
|
|
1401
|
-
var defaultCSSManager = new CSSManager();
|
|
1402
|
-
|
|
1403
1293
|
// ../core/src/rendering/html-renderer.js
|
|
1404
1294
|
var rendererCache = createCacheManager({
|
|
1405
1295
|
maxSize: 1e3,
|