hearald 0.1.0 → 0.1.1

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/CHANGELOG.md CHANGED
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.1.1] - 2026-10-09
11
+
12
+ ### Fixed
13
+
14
+ - The dashboard threw errors the first time it loaded with no data (`Cannot read properties of
15
+ undefined (reading 'map')` and `(reading 'users')`). It now shows zeros and empty menus when there
16
+ are no events, no metrics for the chosen chart context, or no `ui` layout.
17
+
18
+ ### Added
19
+
20
+ - Tests that render the dashboard in a fake browser (happy-dom) against a real hearald router.
21
+
10
22
  ## [0.1.0] - 2026-10-07
11
23
 
12
24
  ### Security
@@ -117,7 +129,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
117
129
 
118
130
  - Initial release of Hearald
119
131
 
120
- [Unreleased]: https://github.com/pariser/hearald/compare/v0.1.0...HEAD
132
+ [Unreleased]: https://github.com/pariser/hearald/compare/v0.1.1...HEAD
133
+ [0.1.1]: https://github.com/pariser/hearald/compare/v0.1.0...v0.1.1
121
134
  [0.1.0]: https://github.com/pariser/hearald/compare/v0.0.5...v0.1.0
122
135
  [0.0.5]: https://github.com/pariser/hearald/compare/v0.0.4...v0.0.5
123
136
  [0.0.4]: https://github.com/pariser/hearald/compare/v0.0.3...v0.0.4
@@ -461,7 +461,7 @@ th {
461
461
  onLoadProgress(i, n);
462
462
 
463
463
  const json = await getDataFn({ n: 1, d: iso(day) });
464
- const v = json.metrics[context][field] || 0;
464
+ const v = json?.metrics?.[context]?.[field] || 0;
465
465
 
466
466
  data.unshift({ date: iso(day), value: v });
467
467
  max = Math.max(max, v);
@@ -687,14 +687,14 @@ th {
687
687
  fetchStats: getJson,
688
688
  });
689
689
 
690
- let UI = [];
690
+ let UI = {};
691
691
 
692
692
  async function fetchUI() {
693
693
  try {
694
694
  const res = await fetch(window.location.href + "/layout");
695
- UI = await res.json();
695
+ UI = (await res.json()) || {};
696
696
  } catch (e) {
697
- UI = [];
697
+ UI = {};
698
698
  }
699
699
  }
700
700
 
@@ -830,7 +830,7 @@ th {
830
830
  name="context"
831
831
  onchange=${(e) => this.changeChartContext(e)}
832
832
  >
833
- ${UI.chartContexts.map(
833
+ ${(UI.chartContexts || []).map(
834
834
  ({ id, menuName }) =>
835
835
  m`
836
836
  <option
@@ -899,7 +899,7 @@ th {
899
899
  `}
900
900
  </div>
901
901
  </section>
902
- ${UI.sections.map((statsSection) => {
902
+ ${(UI.sections || []).map((statsSection) => {
903
903
  return m`
904
904
  <section class="analytics analytics--${statsSection.id}">
905
905
  ${statsSection.menuName !== "" &&
package/dist/index.js CHANGED
@@ -63,7 +63,7 @@
63
63
  onLoadProgress(i, n);
64
64
 
65
65
  const json = await getDataFn({ n: 1, d: iso(day) });
66
- const v = json.metrics[context][field] || 0;
66
+ const v = json?.metrics?.[context]?.[field] || 0;
67
67
 
68
68
  data.unshift({ date: iso(day), value: v });
69
69
  max = Math.max(max, v);
@@ -289,14 +289,14 @@
289
289
  fetchStats: getJson,
290
290
  });
291
291
 
292
- let UI = [];
292
+ let UI = {};
293
293
 
294
294
  async function fetchUI() {
295
295
  try {
296
296
  const res = await fetch(window.location.href + "/layout");
297
- UI = await res.json();
297
+ UI = (await res.json()) || {};
298
298
  } catch (e) {
299
- UI = [];
299
+ UI = {};
300
300
  }
301
301
  }
302
302
 
@@ -432,7 +432,7 @@
432
432
  name="context"
433
433
  onchange=${(e) => this.changeChartContext(e)}
434
434
  >
435
- ${UI.chartContexts.map(
435
+ ${(UI.chartContexts || []).map(
436
436
  ({ id, menuName }) =>
437
437
  m`
438
438
  <option
@@ -501,7 +501,7 @@
501
501
  `}
502
502
  </div>
503
503
  </section>
504
- ${UI.sections.map((statsSection) => {
504
+ ${(UI.sections || []).map((statsSection) => {
505
505
  return m`
506
506
  <section class="analytics analytics--${statsSection.id}">
507
507
  ${statsSection.menuName !== "" &&
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hearald",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "A single server drop-in file system based metrics and analytics library.",
5
5
  "main": "src/index.js",
6
6
  "exports": {
@@ -27,6 +27,7 @@
27
27
  "chalk": "^4.1.0"
28
28
  },
29
29
  "devDependencies": {
30
+ "@happy-dom/global-registrator": "^20.14.6",
30
31
  "@rollup/plugin-commonjs": "^15.1.0",
31
32
  "@rollup/plugin-json": "^4.1.0",
32
33
  "@rollup/plugin-node-resolve": "^13.3.0",
@@ -39,6 +40,7 @@
39
40
  "eslint-plugin-react-hooks": "^4.6.0",
40
41
  "express": "^5.2.1",
41
42
  "express4": "npm:express@^4.21.2",
43
+ "happy-dom": "^20.14.6",
42
44
  "htm": "^3.0.3",
43
45
  "preact": "^10.3.3",
44
46
  "prettier": "2.2.1",
@@ -75,14 +75,14 @@ const getDataFn = ({ n, d, q }) =>
75
75
  fetchStats: getJson,
76
76
  });
77
77
 
78
- let UI = [];
78
+ let UI = {};
79
79
 
80
80
  async function fetchUI() {
81
81
  try {
82
82
  const res = await fetch(window.location.href + "/layout");
83
- UI = await res.json();
83
+ UI = (await res.json()) || {};
84
84
  } catch (e) {
85
- UI = [];
85
+ UI = {};
86
86
  }
87
87
  }
88
88
 
@@ -218,7 +218,7 @@ class App extends Component {
218
218
  name="context"
219
219
  onchange=${(e) => this.changeChartContext(e)}
220
220
  >
221
- ${UI.chartContexts.map(
221
+ ${(UI.chartContexts || []).map(
222
222
  ({ id, menuName }) =>
223
223
  html`
224
224
  <option
@@ -287,7 +287,7 @@ class App extends Component {
287
287
  `}
288
288
  </div>
289
289
  </section>
290
- ${UI.sections.map((statsSection) => {
290
+ ${(UI.sections || []).map((statsSection) => {
291
291
  return html`
292
292
  <section class="analytics analytics--${statsSection.id}">
293
293
  ${statsSection.menuName !== "" &&
@@ -48,7 +48,7 @@ export async function fetchChartData({
48
48
  onLoadProgress(i, n);
49
49
 
50
50
  const json = await getDataFn({ n: 1, d: iso(day) });
51
- const v = json.metrics[context][field] || 0;
51
+ const v = json?.metrics?.[context]?.[field] || 0;
52
52
 
53
53
  data.unshift({ date: iso(day), value: v });
54
54
  max = Math.max(max, v);