runtime-reporter 0.4.0 → 0.4.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/README.md +139 -63
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,19 +1,116 @@
|
|
|
1
1
|
# Runtime Reporter
|
|
2
2
|
|
|
3
|
-
Structured runtime
|
|
3
|
+
Structured runtime reporting that is type-safe, centralized, and production-ready — for frameworks and applications
|
|
4
|
+
|
|
5
|
+
## Why Runtime Reporter?
|
|
6
|
+
|
|
7
|
+
Most projects eventually accumulate:
|
|
8
|
+
|
|
9
|
+
- duplicated log messages
|
|
10
|
+
- inconsistent error wording
|
|
11
|
+
- fragile test assertions
|
|
12
|
+
- accidental exposure of sensitive data
|
|
13
|
+
|
|
14
|
+
Runtime Reporter replaces ad-hoc logging with structured, code-based messaging.
|
|
15
|
+
|
|
16
|
+
## Who is Runtime Reporter for?
|
|
17
|
+
|
|
18
|
+
Use Runtime Reporter if:
|
|
19
|
+
|
|
20
|
+
- you're building a framework or library
|
|
21
|
+
- you want to avoid exposing sensitive information in production
|
|
22
|
+
- you want stable error codes for debugging and tracing runtime behavior
|
|
23
|
+
- you want to avoid bloat from verbose console messages
|
|
24
|
+
- you want a lightweight tool (~2 KB minified) that is easy to use
|
|
25
|
+
- you want to avoid duplicating message text in tests
|
|
4
26
|
|
|
5
27
|
## Features
|
|
6
28
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
29
|
+
If you are new to Runtime Reporter, take a moment to explore the its core features.
|
|
30
|
+
|
|
31
|
+
### Basic usage
|
|
32
|
+
|
|
33
|
+
Getting started is easy. Create a reporter instance with your messages and start logging.
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { createReporter } from "runtime-reporter";
|
|
37
|
+
|
|
38
|
+
const reporter = createReporter({
|
|
39
|
+
ERR01: "MyComponent failed at mount",
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
reporter.error("ERR01");
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Code-based messaging
|
|
46
|
+
|
|
47
|
+
Replace inline strings with centralized, code-based identifiers.
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
// Without runtime-reporter (logs "MyComponent failed at mount")
|
|
51
|
+
console.error("MyComponent failed at mount");
|
|
52
|
+
|
|
53
|
+
// With runtime-reporter (logs "MyComponent failed at mount (ERR01)")
|
|
54
|
+
reporter.error("ERR01");
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Dynamic messages
|
|
58
|
+
|
|
59
|
+
Inject runtime data into your messages via message templates and tokenized variables.
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
const reporter = createReporter({
|
|
63
|
+
ERR01: "{{ componentName }} failed at {{ phase }}",
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
reporter.error("ERR01", { componentName: "MyComponent", phase: "mount" });
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Type safety
|
|
70
|
+
|
|
71
|
+
Annotate your messages to get autocomplete and compile-time validation for message codes and token names.
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
const messages: RuntimeReporterMessages<{
|
|
75
|
+
code: "ERR01";
|
|
76
|
+
template: "{{ componentName }} failed at {{ phase }}";
|
|
77
|
+
tokens: "componentName" | "phase";
|
|
78
|
+
}> = {
|
|
79
|
+
ERR01: "{{ componentName }} failed at {{ phase }}",
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const reporter = createReporter(messages);
|
|
83
|
+
|
|
84
|
+
reporter.error("ERR01", { componentName: "MyComponent", phase: "mount" }); // ✅ Autocomplete
|
|
85
|
+
reporter.error("ERR01", { componentName: "MyComponent" }); // ❌ TypeScript Error: "phase" is required
|
|
86
|
+
reporter.error("ERR02", { componentName: "MyComponent", phase: "mount" }); // ❌ TypeScript Error: "ERR02" is not a valid message code
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Production builds
|
|
90
|
+
|
|
91
|
+
Pass an empty object to the `createReporter` function in production for better security and a smaller bundle size.
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
const reporter = createReporter(
|
|
95
|
+
process.env.NODE_ENV === "production" ? ({} as typeof messages) : messages
|
|
96
|
+
);
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Test friendly
|
|
100
|
+
|
|
101
|
+
Assert against resolved messages without duplicating message text in your test environment.
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
it("should log error if component fails to mount", () => {
|
|
105
|
+
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
106
|
+
|
|
107
|
+
render(<MyComponent />);
|
|
108
|
+
|
|
109
|
+
expect(console.error).toHaveBeenCalledWith(
|
|
110
|
+
reporter.message("ERR01", { componentName: "MyComponent", phase: "mount" })
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
```
|
|
17
114
|
|
|
18
115
|
## Installation
|
|
19
116
|
|
|
@@ -21,14 +118,14 @@ Structured runtime events for applications and frameworks. A composable foundati
|
|
|
21
118
|
npm install runtime-reporter
|
|
22
119
|
```
|
|
23
120
|
|
|
24
|
-
##
|
|
25
|
-
|
|
26
|
-
### 1) Define your messages
|
|
121
|
+
## Quick start
|
|
27
122
|
|
|
28
|
-
|
|
123
|
+
A copy-and-paste example of how to use Runtime Reporter in your project.
|
|
29
124
|
|
|
30
125
|
```ts
|
|
31
|
-
|
|
126
|
+
// src/runtime-reporter.ts
|
|
127
|
+
|
|
128
|
+
import { createReporter, type RuntimeReporterMessages } from "runtime-reporter";
|
|
32
129
|
|
|
33
130
|
const messages: RuntimeReporterMessages<
|
|
34
131
|
| {
|
|
@@ -37,38 +134,34 @@ const messages: RuntimeReporterMessages<
|
|
|
37
134
|
tokens: "componentName" | "phase";
|
|
38
135
|
}
|
|
39
136
|
| {
|
|
40
|
-
code: "
|
|
41
|
-
template: "
|
|
137
|
+
code: "ERR02";
|
|
138
|
+
template: "Failed to load configuration";
|
|
42
139
|
}
|
|
43
140
|
> = {
|
|
44
141
|
ERR01: "{{ componentName }} failed at {{ phase }}",
|
|
45
|
-
|
|
142
|
+
ERR02: "Failed to load configuration",
|
|
46
143
|
};
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### 2) Create the reporter
|
|
50
|
-
|
|
51
|
-
Pass your messages to `createReporter()` to create a reporter instance.
|
|
52
144
|
|
|
53
|
-
|
|
54
|
-
|
|
145
|
+
/** The runtime reporter for <project-name> */
|
|
146
|
+
const reporter = createReporter(messages);
|
|
55
147
|
|
|
56
|
-
export
|
|
57
|
-
// Pass an empty object in production for better security and a smaller bundle size
|
|
58
|
-
process.env.NODE_ENV === "production" ? ({} as typeof messages) : messages
|
|
59
|
-
);
|
|
148
|
+
export default reporter;
|
|
60
149
|
```
|
|
61
150
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
Call the various reporter methods wherever you need them.
|
|
151
|
+
Once your project's reporter is created, you can import and use it wherever you need it.
|
|
65
152
|
|
|
66
153
|
```ts
|
|
67
|
-
|
|
68
|
-
// logs: "Router failed at mount (ERR01)"
|
|
154
|
+
// src/my-component.ts
|
|
69
155
|
|
|
70
|
-
reporter
|
|
71
|
-
|
|
156
|
+
import { reporter } from "./runtime-reporter";
|
|
157
|
+
|
|
158
|
+
export function MyComponent() {
|
|
159
|
+
useEffect(() => {
|
|
160
|
+
reporter.error("ERR01", { componentName: "MyComponent", phase: "mount" });
|
|
161
|
+
}, []);
|
|
162
|
+
|
|
163
|
+
return <div>My Component</div>;
|
|
164
|
+
}
|
|
72
165
|
```
|
|
73
166
|
|
|
74
167
|
## API
|
|
@@ -146,37 +239,20 @@ reporter.error("ERR01", { componentName: "Router", phase: "mount" });
|
|
|
146
239
|
The `message` method returns the resolved string without side effects, allowing you to validate precise messaging without duplicating text.
|
|
147
240
|
|
|
148
241
|
```ts
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
describe("reporter messages", () => {
|
|
153
|
-
it("consoles error ERR01 correctly", () => {
|
|
154
|
-
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
155
|
-
reporter.error("ERR01", { componentName: "Widget" });
|
|
156
|
-
|
|
157
|
-
expect(console.error).toHaveBeenCalledWith(
|
|
158
|
-
reporter.message("ERR01", { componentName: "Widget" })
|
|
159
|
-
);
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
### Using the reporter without TypeScript
|
|
165
|
-
|
|
166
|
-
You can use the reporter without TypeScript, you will just lose the type safety and autocomplete.
|
|
242
|
+
it("should log error if component fails to mount", () => {
|
|
243
|
+
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
167
244
|
|
|
168
|
-
|
|
169
|
-
import { createReporter } from "runtime-reporter";
|
|
245
|
+
render(<MyComponent />);
|
|
170
246
|
|
|
171
|
-
|
|
172
|
-
|
|
247
|
+
expect(console.error).toHaveBeenCalledWith(
|
|
248
|
+
reporter.message("ERR01", { componentName: "MyComponent", phase: "mount" })
|
|
249
|
+
);
|
|
173
250
|
});
|
|
174
|
-
|
|
175
|
-
reporter.error("ERR01", { componentName: "Router", phase: "mount" });
|
|
176
|
-
// logs: "Router failed at mount (ERR01)"
|
|
177
251
|
```
|
|
178
252
|
|
|
179
|
-
|
|
253
|
+
### Type safety without TypeScript
|
|
254
|
+
|
|
255
|
+
You can still get the same benefits as TypeScript by using JSDoc-style type annotations.
|
|
180
256
|
|
|
181
257
|
```js
|
|
182
258
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "runtime-reporter",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"description": "Structured runtime
|
|
3
|
+
"version": "0.4.2",
|
|
4
|
+
"description": "Structured runtime reporting that is type-safe, centralized, and production-ready.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.js",
|