runtime-reporter 0.4.1 → 0.4.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/README.md +156 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -3
- package/dist/index.d.ts +8 -3
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,21 +1,121 @@
|
|
|
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
4
|
|
|
5
|
-
|
|
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
|
|
6
26
|
|
|
7
27
|
## Features
|
|
8
28
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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 to 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 to mount")
|
|
51
|
+
console.error("MyComponent failed to mount");
|
|
52
|
+
|
|
53
|
+
// With runtime-reporter (logs "MyComponent failed to 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 to mount";
|
|
77
|
+
tokens: "componentName";
|
|
78
|
+
}> = {
|
|
79
|
+
ERR01: "{{ componentName }} failed to mount",
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const reporter = createReporter(messages);
|
|
83
|
+
|
|
84
|
+
// ✅ Autocomplete
|
|
85
|
+
reporter.error("ERR01", { componentName: "MyComponent" });
|
|
86
|
+
|
|
87
|
+
// ❌ TypeScript Error: "ERR02" is not a valid message code
|
|
88
|
+
reporter.error("ERR02", { componentName: "MyComponent" });
|
|
89
|
+
|
|
90
|
+
// ❌ TypeScript Error: "componentName" token is required
|
|
91
|
+
reporter.error("ERR01");
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Production environments
|
|
95
|
+
|
|
96
|
+
Pass an empty object to the `createReporter` function in production environments for better security and a smaller bundle size.
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
const reporter = createReporter(
|
|
100
|
+
process.env.NODE_ENV === "production" ? ({} as typeof messages) : messages
|
|
101
|
+
);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Test friendly
|
|
105
|
+
|
|
106
|
+
Assert against resolved messages without duplicating message text in your test environment.
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
it("should log error if component fails to mount", () => {
|
|
110
|
+
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
111
|
+
|
|
112
|
+
render(<MyComponent />);
|
|
113
|
+
|
|
114
|
+
expect(console.error).toHaveBeenCalledWith(
|
|
115
|
+
reporter.message("ERR01", { componentName: "MyComponent" })
|
|
116
|
+
);
|
|
117
|
+
});
|
|
118
|
+
```
|
|
19
119
|
|
|
20
120
|
## Installation
|
|
21
121
|
|
|
@@ -23,54 +123,56 @@ Modern applications often rely on complex logging solutions or ad-hoc messaging
|
|
|
23
123
|
npm install runtime-reporter
|
|
24
124
|
```
|
|
25
125
|
|
|
26
|
-
##
|
|
27
|
-
|
|
28
|
-
### 1) Define your messages
|
|
126
|
+
## Quick start
|
|
29
127
|
|
|
30
|
-
|
|
128
|
+
A copy-and-paste example of how to use Runtime Reporter in your project.
|
|
31
129
|
|
|
32
130
|
```ts
|
|
33
|
-
|
|
131
|
+
// src/runtime-reporter.ts
|
|
132
|
+
|
|
133
|
+
import { createReporter, type RuntimeReporterMessages } from "runtime-reporter";
|
|
34
134
|
|
|
35
135
|
const messages: RuntimeReporterMessages<
|
|
36
136
|
| {
|
|
37
137
|
code: "ERR01";
|
|
38
|
-
template: "{{ componentName }} failed
|
|
39
|
-
tokens: "componentName"
|
|
138
|
+
template: "{{ componentName }} failed to mount";
|
|
139
|
+
tokens: "componentName";
|
|
140
|
+
}
|
|
141
|
+
| {
|
|
142
|
+
code: "ERR02";
|
|
143
|
+
template: "Failed to load configuration";
|
|
40
144
|
}
|
|
41
145
|
| {
|
|
42
|
-
code: "
|
|
43
|
-
template: "
|
|
146
|
+
code: "ERR03";
|
|
147
|
+
template: "Failed to fetch {{ resource }} from {{ url }}";
|
|
148
|
+
tokens: "resource" | "url";
|
|
44
149
|
}
|
|
45
150
|
> = {
|
|
46
|
-
ERR01: "{{ componentName }} failed
|
|
47
|
-
|
|
151
|
+
ERR01: "{{ componentName }} failed to mount",
|
|
152
|
+
ERR02: "Failed to load configuration",
|
|
153
|
+
ERR03: "Failed to fetch {{ resource }} from {{ url }}",
|
|
48
154
|
};
|
|
49
|
-
```
|
|
50
155
|
|
|
51
|
-
|
|
156
|
+
/** The runtime reporter for <project-name> */
|
|
157
|
+
const reporter = createReporter(messages);
|
|
52
158
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
```ts
|
|
56
|
-
import { createReporter } from "runtime-reporter";
|
|
57
|
-
|
|
58
|
-
export const reporter = createReporter(
|
|
59
|
-
// Pass an empty object in production for better security and a smaller bundle size
|
|
60
|
-
process.env.NODE_ENV === "production" ? ({} as typeof messages) : messages
|
|
61
|
-
);
|
|
159
|
+
export default reporter;
|
|
62
160
|
```
|
|
63
161
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
Call the various reporter methods wherever you need them.
|
|
162
|
+
Once your project's reporter is created, you can import and use it wherever you need it like this:
|
|
67
163
|
|
|
68
164
|
```ts
|
|
69
|
-
|
|
70
|
-
|
|
165
|
+
// src/my-component.ts
|
|
166
|
+
|
|
167
|
+
import { reporter } from "./runtime-reporter";
|
|
71
168
|
|
|
72
|
-
|
|
73
|
-
|
|
169
|
+
export function MyComponent() {
|
|
170
|
+
useEffect(() => {
|
|
171
|
+
reporter.error("ERR01", { componentName: "MyComponent", phase: "mount" });
|
|
172
|
+
}, []);
|
|
173
|
+
|
|
174
|
+
return <div>My Component</div>;
|
|
175
|
+
}
|
|
74
176
|
```
|
|
75
177
|
|
|
76
178
|
## API
|
|
@@ -113,17 +215,16 @@ const reporter = createReporter(messages, {
|
|
|
113
215
|
formatMessage: (msg, code) => `[${code}] ${msg}`,
|
|
114
216
|
});
|
|
115
217
|
|
|
116
|
-
reporter.message("
|
|
117
|
-
// "[
|
|
218
|
+
reporter.message("ERR01", { componentName: "MyComponent" });
|
|
219
|
+
// "[ERR01] MyComponent failed to mount"
|
|
118
220
|
```
|
|
119
221
|
|
|
120
|
-
###
|
|
222
|
+
### Calling `fail()` in production
|
|
121
223
|
|
|
122
|
-
When the `createReporter` function
|
|
224
|
+
When the `createReporter` function provided an empty message set in production, the `fail` method will use the customizable `defaultTemplate` option which defaults to "An error occurred". This message is intended to be generic so that it does not reveal sensitive information about the system, while still providing a code for debugging purposes.
|
|
123
225
|
|
|
124
226
|
```ts
|
|
125
227
|
const reporter = createReporter(
|
|
126
|
-
// Pass an empty object in production for better security and a smaller bundle size
|
|
127
228
|
process.env.NODE_ENV === "production" ? ({} as typeof messages) : messages
|
|
128
229
|
);
|
|
129
230
|
|
|
@@ -131,54 +232,25 @@ reporter.fail("ERR01", { componentName: "Router", phase: "mount" });
|
|
|
131
232
|
// throws: "An error occurred (ERR01)"
|
|
132
233
|
```
|
|
133
234
|
|
|
134
|
-
The remaining reporter methods will not log anything in production when the code is missing from the message set.
|
|
135
|
-
|
|
136
|
-
```ts
|
|
137
|
-
const reporter = createReporter(
|
|
138
|
-
// Pass an empty object in production for better security and a smaller bundle size
|
|
139
|
-
process.env.NODE_ENV === "production" ? ({} as typeof messages) : messages
|
|
140
|
-
);
|
|
141
|
-
|
|
142
|
-
reporter.error("ERR01", { componentName: "Router", phase: "mount" });
|
|
143
|
-
// does not log anything
|
|
144
|
-
```
|
|
145
|
-
|
|
146
235
|
### Using `message()` in tests
|
|
147
236
|
|
|
148
237
|
The `message` method returns the resolved string without side effects, allowing you to validate precise messaging without duplicating text.
|
|
149
238
|
|
|
150
239
|
```ts
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
describe("reporter messages", () => {
|
|
155
|
-
it("consoles error ERR01 correctly", () => {
|
|
156
|
-
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
157
|
-
reporter.error("ERR01", { componentName: "Widget" });
|
|
158
|
-
|
|
159
|
-
expect(console.error).toHaveBeenCalledWith(
|
|
160
|
-
reporter.message("ERR01", { componentName: "Widget" })
|
|
161
|
-
);
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
```
|
|
240
|
+
it("should log error if component fails to mount", () => {
|
|
241
|
+
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
165
242
|
|
|
166
|
-
|
|
243
|
+
render(<MyComponent />);
|
|
167
244
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
import { createReporter } from "runtime-reporter";
|
|
172
|
-
|
|
173
|
-
const reporter = createReporter({
|
|
174
|
-
ERR01: "{{ componentName }} failed at {{ phase }}",
|
|
245
|
+
expect(console.error).toHaveBeenCalledWith(
|
|
246
|
+
reporter.message("ERR01", { componentName: "MyComponent", phase: "mount" })
|
|
247
|
+
);
|
|
175
248
|
});
|
|
176
|
-
|
|
177
|
-
reporter.error("ERR01", { componentName: "Router", phase: "mount" });
|
|
178
|
-
// logs: "Router failed at mount (ERR01)"
|
|
179
249
|
```
|
|
180
250
|
|
|
181
|
-
|
|
251
|
+
### Type safety without TypeScript
|
|
252
|
+
|
|
253
|
+
You can still get the same benefits as TypeScript by using JSDoc-style type annotations.
|
|
182
254
|
|
|
183
255
|
```js
|
|
184
256
|
/**
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * The type information for a single runtime reporter message\n * @since v0.1.0\n */\nexport type RuntimeReporterMessage = {\n code: string;\n template: string;\n tokens?: string;\n};\n\n/**\n * The type for a full list of messages with their associated code and template\n * @since v0.1.0\n */\nexport type RuntimeReporterMessages<T extends RuntimeReporterMessage> = {\n [K in T[\"code\"]]: Extract<T, { code: K }>[\"template\"];\n};\n\n/**\n * The type for the supported values of a placeholder token\n * @since v0.1.0\n */\nexport type RuntimeReporterToken = string | number | boolean | Error | null | undefined;\n\n/**\n * The type for a record of placeholder token names and their values\n * @since v0.2.0\n */\nexport type RuntimeReporterTokens = Record<string, RuntimeReporterToken>;\n\n/**\n * A utility type used to determine the second argument of the runtime reporter methods\n * @private\n */\ntype ReporterTokensArgs<T extends RuntimeReporterMessage, U extends T[\"code\"]> = Extract<\n T,\n { code: U }\n>[\"tokens\"] extends infer Tokens\n ? [Tokens] extends [string]\n ? [tokens: Record<Tokens, RuntimeReporterToken>]\n : []\n : [];\n\n/**\n * Return type for message(); displays the template + code in default format on hover.\n * The runtime value is the resolved string (tokens substituted); the type is for DX only.\n * @private\n */\ntype MessageReturnType<T extends RuntimeReporterMessage, U extends T[\"code\"]> =\n Extract<T, { code: U }> extends { template: infer Template }\n ? Template extends string\n ? `${Template} (${U})`\n : string\n : string;\n\n/**\n * The runtime report object with all of it's associated methods; the result\n * of the primary export: `createReporter`\n * @private\n */\ninterface RuntimeReporter<T extends RuntimeReporterMessage> {\n /**\n * Retrieves the full text of the targeted message\n *\n * _Note: As a convenience, the return type will attempt to show the literal type of the template\n * pattern and code suffix (in the default format) for the message on hover; the actual output may\n * vary based on the tokens provided and the `formatMessage` option._\n *\n * _Tip: This method is particularly useful in the test environment; allowing you\n * to make precise assertions without having to duplicate any of the raw message text._\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n message<U extends T[\"code\"]>(\n code: U,\n ...args: ReporterTokensArgs<T, U>\n ): MessageReturnType<T, U>;\n\n /**\n * Logs a warning to the console with the full text of the targeted message in non-production environments\n *\n * _Note: This method will only log when the message associated with the code is found;\n * meaning it will not be called in production if the `createReporter` function\n * is provided an empty message set._\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n warn<U extends T[\"code\"]>(code: U, ...args: ReporterTokensArgs<T, U>): void;\n\n /**\n * Logs an error to the console with the full text of the targeted message in non-production environments\n *\n * _Note: This method will only log when the message associated with the code is found;\n * meaning it will not be called in production if the `createReporter` function\n * is provided an empty message set._\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n error<U extends T[\"code\"]>(code: U, ...args: ReporterTokensArgs<T, U>): void;\n\n /**\n * Logs a message to the console with the full text of the targeted message in non-production environments\n *\n * _Note: This method will only log when the message associated with the code is found;\n * meaning it will not be called in production if the `createReporter` function\n * is provided an empty message set._\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n log<U extends T[\"code\"]>(code: U, ...args: ReporterTokensArgs<T, U>): void;\n\n /**\n * Throws an error with the full text of the targeted message in all environments\n *\n * _Note: When the `createReporter` function is called in production with an empty\n * message set, this method will use the \"defaultTemplate\" option in this format: \"<defaultTemplate> (<code>)\"_\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n fail<U extends T[\"code\"]>(code: U, ...args: ReporterTokensArgs<T, U>): void;\n}\n\nexport interface RuntimeReporterOptions {\n /**\n * A hook to format the message text universally. By default, it\n * outputs the message in the following format: \"<message> (<code>)\"\n * @param message The resolved message text; the placeholders have been replaced by their token values\n * @param code The unique code associated with the message\n * @returns The final, fully formatted message\n */\n formatMessage?: (message: string, code: string) => string;\n\n /**\n * The default template to fallback on when a provided code does not\n * have an associated message. Defaults to \"An error occurred\"\n *\n * _Note: This is only used when the `fail` method is called in production\n * environments when the `createReporter` function is provided an empty message set._\n */\n defaultTemplate?: string;\n}\n\n/**\n * Resolves the message text via the message template and the associated tokens\n * @param template The template string for the reported message\n * @param tokens The token names and values for the instance\n * @returns The resolved message text; returns an empty string if the template is falsy\n */\nconst resolveTemplate = function resolveTemplate(\n template: string,\n tokens?: Record<string, RuntimeReporterToken>\n): string {\n let message = template;\n\n if (message) {\n Object.entries(tokens || {}).forEach((entry) => {\n const [token, value] = entry;\n const replace = value instanceof Error ? value.message : String(value ?? \"\");\n const sanitized = token.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n message = message.replace(new RegExp(`\\\\{\\\\{\\\\s*${sanitized}\\\\s*\\\\}\\\\}`, \"g\"), replace);\n });\n }\n\n return message;\n};\n\n/**\n * Creates a reporter object with various helpful runtime methods\n * @param messages The messages record organized by code and template\n * @param options Optional configuration options\n * @returns A runtime report object\n */\nexport function createReporter<T extends RuntimeReporterMessage>(\n messages: RuntimeReporterMessages<T>,\n options: RuntimeReporterOptions = {}\n): RuntimeReporter<T> {\n const {\n formatMessage = (message, code) => `${message} (${code})`,\n defaultTemplate = \"An error occurred\",\n } = options;\n const messagesByCode = messages as Record<string, string>;\n\n /**\n * Retrieves the final message for a give code and its associated tokens\n * @param code The unique code associated with the message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n * @returns The fully resolve message or an empty string if there was no template\n */\n const getMessage = function getMessage(\n code: string,\n ...args: Array<Record<string, RuntimeReporterToken>>\n ): string {\n const template = messagesByCode[code] || defaultTemplate;\n const tokens = args[0];\n const text = resolveTemplate(template, tokens);\n return formatMessage(text, code);\n };\n\n return {\n message: (code, ...args) =>\n getMessage(code, ...args) as MessageReturnType<T, typeof code & T[\"code\"]>,\n error: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messagesByCode[code]) console.error(message);\n },\n warn: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messagesByCode[code]) console.warn(message);\n },\n log: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messagesByCode[code]) console.log(message);\n },\n fail: (code, ...args) => {\n const message = getMessage(code, ...args);\n throw new Error(message);\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAoJA,IAAM,kBAAkB,SAASA,iBAC7B,UACA,QACM;AACN,MAAI,UAAU;AAEd,MAAI,SAAS;AACT,WAAO,QAAQ,UAAU,CAAC,CAAC,EAAE,QAAQ,CAAC,UAAU;AAC5C,YAAM,CAAC,OAAO,KAAK,IAAI;AACvB,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,SAAS,EAAE;AAC3E,YAAM,YAAY,MAAM,QAAQ,uBAAuB,MAAM;AAC7D,gBAAU,QAAQ,QAAQ,IAAI,OAAO,aAAa,SAAS,cAAc,GAAG,GAAG,OAAO;AAAA,IAC1F,CAAC;AAAA,EACL;AAEA,SAAO;AACX;AAQO,SAAS,eACZ,UACA,UAAkC,CAAC,GACjB;AAClB,QAAM;AAAA,IACF,gBAAgB,CAAC,SAAS,SAAS,GAAG,OAAO,KAAK,IAAI;AAAA,IACtD,kBAAkB;AAAA,EACtB,IAAI;AACJ,QAAM,iBAAiB;AAQvB,QAAM,aAAa,SAASC,YACxB,SACG,MACG;AACN,UAAM,WAAW,eAAe,IAAI,KAAK;AACzC,UAAM,SAAS,KAAK,CAAC;AACrB,UAAM,OAAO,gBAAgB,UAAU,MAAM;AAC7C,WAAO,cAAc,MAAM,IAAI;AAAA,EACnC;AAEA,SAAO;AAAA,IACH,SAAS,CAAC,SAAS,SACf,WAAW,MAAM,GAAG,IAAI;AAAA,IAC5B,OAAO,CAAC,SAAS,SAAS;AACtB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,eAAe,IAAI,EAAG,SAAQ,MAAM,OAAO;AAAA,IACnD;AAAA,IACA,MAAM,CAAC,SAAS,SAAS;AACrB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,eAAe,IAAI,EAAG,SAAQ,KAAK,OAAO;AAAA,IAClD;AAAA,IACA,KAAK,CAAC,SAAS,SAAS;AACpB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,eAAe,IAAI,EAAG,SAAQ,IAAI,OAAO;AAAA,IACjD;AAAA,IACA,MAAM,CAAC,SAAS,SAAS;AACrB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,YAAM,IAAI,MAAM,OAAO;AAAA,IAC3B;AAAA,EACJ;AACJ;","names":["resolveTemplate","getMessage"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * The type information for a single runtime reporter message\n * @since v0.1.0\n */\nexport type RuntimeReporterMessage = {\n code: string;\n template: string;\n tokens?: string;\n};\n\n/**\n * The type for a full list of messages with their associated code and template\n * @since v0.1.0\n */\nexport type RuntimeReporterMessages<T extends RuntimeReporterMessage> = {\n [K in T[\"code\"]]: Extract<T, { code: K }>[\"template\"];\n};\n\n/**\n * The type for the supported values of a placeholder token\n * @since v0.1.0\n */\nexport type RuntimeReporterToken = string | number | boolean | Error | null | undefined;\n\n/**\n * The type for a record of placeholder token names and their values\n * @since v0.2.0\n */\nexport type RuntimeReporterTokens = Record<string, RuntimeReporterToken>;\n\n/**\n * A utility type used to determine the second argument of the runtime reporter methods\n * @private\n */\ntype ReporterTokensArgs<T extends RuntimeReporterMessage, U extends T[\"code\"]> = Extract<\n T,\n { code: U }\n>[\"tokens\"] extends infer Tokens\n ? [Tokens] extends [string]\n ? [tokens: Record<Tokens, RuntimeReporterToken>]\n : []\n : [];\n\n/**\n * Return type for message(); displays the template + code in default format on hover.\n * The runtime value is the resolved string (tokens substituted); the type is for DX only.\n * @private\n */\ntype MessageReturnType<T extends RuntimeReporterMessage, U extends T[\"code\"]> =\n Extract<T, { code: U }> extends { template: infer Template }\n ? Template extends string\n ? `${Template} (${U})`\n : string\n : string;\n\n/**\n * The runtime report object with all of it's associated methods;\n * the result of the primary export: `createReporter`\n * @private\n */\ninterface RuntimeReporter<T extends RuntimeReporterMessage> {\n /**\n * Retrieves the full text of the targeted message\n *\n * _Note: As a convenience, the return type will attempt to show the literal type of the template\n * pattern and code suffix (in the default format) for the message on hover; the actual output may\n * vary based on the tokens provided and the `formatMessage` option._\n *\n * _Tip: This method is particularly useful in the test environment; allowing you\n * to make precise assertions without having to duplicate any of the raw message text._\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n message<U extends T[\"code\"]>(\n code: U,\n ...args: ReporterTokensArgs<T, U>\n ): MessageReturnType<T, U>;\n\n /**\n * Logs a warning to the console with the full text of the targeted message in non-production environments\n *\n * _Note: This method will only log when the message associated with the code is found;\n * meaning it will not be called in production if the `createReporter` function\n * is provided an empty message set._\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n warn<U extends T[\"code\"]>(code: U, ...args: ReporterTokensArgs<T, U>): void;\n\n /**\n * Logs an error to the console with the full text of the targeted message in non-production environments\n *\n * _Note: This method will only log when the message associated with the code is found;\n * meaning it will not be called in production if the `createReporter` function\n * is provided an empty message set._\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n error<U extends T[\"code\"]>(code: U, ...args: ReporterTokensArgs<T, U>): void;\n\n /**\n * Logs a message to the console with the full text of the targeted message in non-production environments\n *\n * _Note: This method will only log when the message associated with the code is found;\n * meaning it will not be called in production if the `createReporter` function\n * is provided an empty message set._\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n log<U extends T[\"code\"]>(code: U, ...args: ReporterTokensArgs<T, U>): void;\n\n /**\n * Throws an error with the full text of the targeted message in all environments\n *\n * _Note: When the `createReporter` function is called in production with an empty\n * message set, this method will use the \"defaultTemplate\" option in this format: \"<defaultTemplate> (<code>)\"_\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n fail<U extends T[\"code\"]>(code: U, ...args: ReporterTokensArgs<T, U>): void;\n}\n\n/**\n * The configuration options for createReporter()\n * @since v0.1.0\n */\nexport interface RuntimeReporterOptions {\n /**\n * A hook to format the message text universally. By default, it\n * outputs the message in the following format: \"<message> (<code>)\"\n * @param message The resolved message text; the placeholders have been replaced by their token values\n * @param code The unique code associated with the message\n * @returns The final, fully formatted message\n */\n formatMessage?: (message: string, code: string) => string;\n\n /**\n * The default template to fallback on when a provided code does not\n * have an associated message. Defaults to \"An error occurred\"\n *\n * _Note: This is only used when the `fail` method is called in production\n * environments when the `createReporter` function is provided an empty message set._\n */\n defaultTemplate?: string;\n}\n\n/**\n * Resolves the message text via the message template and the associated tokens\n * @param template The template string for the reported message\n * @param tokens The token names and values for the instance\n * @returns The resolved message text; returns an empty string if the template is falsy\n * @private\n */\nconst resolveTemplate = function resolveTemplate(\n template: string,\n tokens?: Record<string, RuntimeReporterToken>\n): string {\n let message = template;\n\n if (message) {\n Object.entries(tokens || {}).forEach((entry) => {\n const [token, value] = entry;\n const replace = value instanceof Error ? value.message : String(value ?? \"\");\n const sanitized = token.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n message = message.replace(new RegExp(`\\\\{\\\\{\\\\s*${sanitized}\\\\s*\\\\}\\\\}`, \"g\"), replace);\n });\n }\n\n return message;\n};\n\n/**\n * Creates a new runtime reporter object with all of it's associated methods\n * @param messages The messages record organized by code and template\n * @param options Optional configuration options\n * @returns A runtime report object\n * @since v0.1.0\n */\nexport function createReporter<T extends RuntimeReporterMessage>(\n messages: RuntimeReporterMessages<T>,\n options: RuntimeReporterOptions = {}\n): RuntimeReporter<T> {\n const {\n formatMessage = (message, code) => `${message} (${code})`,\n defaultTemplate = \"An error occurred\",\n } = options;\n const messagesByCode = messages as Record<string, string>;\n\n /**\n * Retrieves the final message for a give code and its associated tokens\n * @param code The unique code associated with the message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n * @returns The fully resolve message or an empty string if there was no template\n */\n const getMessage = function getMessage(\n code: string,\n ...args: Array<Record<string, RuntimeReporterToken>>\n ): string {\n const template = messagesByCode[code] || defaultTemplate;\n const tokens = args[0];\n const text = resolveTemplate(template, tokens);\n return formatMessage(text, code);\n };\n\n return {\n message: (code, ...args) =>\n getMessage(code, ...args) as MessageReturnType<T, typeof code & T[\"code\"]>,\n error: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messagesByCode[code]) console.error(message);\n },\n warn: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messagesByCode[code]) console.warn(message);\n },\n log: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messagesByCode[code]) console.log(message);\n },\n fail: (code, ...args) => {\n const message = getMessage(code, ...args);\n throw new Error(message);\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAyJA,IAAM,kBAAkB,SAASA,iBAC7B,UACA,QACM;AACN,MAAI,UAAU;AAEd,MAAI,SAAS;AACT,WAAO,QAAQ,UAAU,CAAC,CAAC,EAAE,QAAQ,CAAC,UAAU;AAC5C,YAAM,CAAC,OAAO,KAAK,IAAI;AACvB,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,SAAS,EAAE;AAC3E,YAAM,YAAY,MAAM,QAAQ,uBAAuB,MAAM;AAC7D,gBAAU,QAAQ,QAAQ,IAAI,OAAO,aAAa,SAAS,cAAc,GAAG,GAAG,OAAO;AAAA,IAC1F,CAAC;AAAA,EACL;AAEA,SAAO;AACX;AASO,SAAS,eACZ,UACA,UAAkC,CAAC,GACjB;AAClB,QAAM;AAAA,IACF,gBAAgB,CAAC,SAAS,SAAS,GAAG,OAAO,KAAK,IAAI;AAAA,IACtD,kBAAkB;AAAA,EACtB,IAAI;AACJ,QAAM,iBAAiB;AAQvB,QAAM,aAAa,SAASC,YACxB,SACG,MACG;AACN,UAAM,WAAW,eAAe,IAAI,KAAK;AACzC,UAAM,SAAS,KAAK,CAAC;AACrB,UAAM,OAAO,gBAAgB,UAAU,MAAM;AAC7C,WAAO,cAAc,MAAM,IAAI;AAAA,EACnC;AAEA,SAAO;AAAA,IACH,SAAS,CAAC,SAAS,SACf,WAAW,MAAM,GAAG,IAAI;AAAA,IAC5B,OAAO,CAAC,SAAS,SAAS;AACtB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,eAAe,IAAI,EAAG,SAAQ,MAAM,OAAO;AAAA,IACnD;AAAA,IACA,MAAM,CAAC,SAAS,SAAS;AACrB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,eAAe,IAAI,EAAG,SAAQ,KAAK,OAAO;AAAA,IAClD;AAAA,IACA,KAAK,CAAC,SAAS,SAAS;AACpB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,eAAe,IAAI,EAAG,SAAQ,IAAI,OAAO;AAAA,IACjD;AAAA,IACA,MAAM,CAAC,SAAS,SAAS;AACrB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,YAAM,IAAI,MAAM,OAAO;AAAA,IAC3B;AAAA,EACJ;AACJ;","names":["resolveTemplate","getMessage"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -44,8 +44,8 @@ type MessageReturnType<T extends RuntimeReporterMessage, U extends T["code"]> =
|
|
|
44
44
|
template: infer Template;
|
|
45
45
|
} ? Template extends string ? `${Template} (${U})` : string : string;
|
|
46
46
|
/**
|
|
47
|
-
* The runtime report object with all of it's associated methods;
|
|
48
|
-
* of the primary export: `createReporter`
|
|
47
|
+
* The runtime report object with all of it's associated methods;
|
|
48
|
+
* the result of the primary export: `createReporter`
|
|
49
49
|
* @private
|
|
50
50
|
*/
|
|
51
51
|
interface RuntimeReporter<T extends RuntimeReporterMessage> {
|
|
@@ -102,6 +102,10 @@ interface RuntimeReporter<T extends RuntimeReporterMessage> {
|
|
|
102
102
|
*/
|
|
103
103
|
fail<U extends T["code"]>(code: U, ...args: ReporterTokensArgs<T, U>): void;
|
|
104
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* The configuration options for createReporter()
|
|
107
|
+
* @since v0.1.0
|
|
108
|
+
*/
|
|
105
109
|
interface RuntimeReporterOptions {
|
|
106
110
|
/**
|
|
107
111
|
* A hook to format the message text universally. By default, it
|
|
@@ -121,10 +125,11 @@ interface RuntimeReporterOptions {
|
|
|
121
125
|
defaultTemplate?: string;
|
|
122
126
|
}
|
|
123
127
|
/**
|
|
124
|
-
* Creates a reporter object with
|
|
128
|
+
* Creates a new runtime reporter object with all of it's associated methods
|
|
125
129
|
* @param messages The messages record organized by code and template
|
|
126
130
|
* @param options Optional configuration options
|
|
127
131
|
* @returns A runtime report object
|
|
132
|
+
* @since v0.1.0
|
|
128
133
|
*/
|
|
129
134
|
declare function createReporter<T extends RuntimeReporterMessage>(messages: RuntimeReporterMessages<T>, options?: RuntimeReporterOptions): RuntimeReporter<T>;
|
|
130
135
|
|
package/dist/index.d.ts
CHANGED
|
@@ -44,8 +44,8 @@ type MessageReturnType<T extends RuntimeReporterMessage, U extends T["code"]> =
|
|
|
44
44
|
template: infer Template;
|
|
45
45
|
} ? Template extends string ? `${Template} (${U})` : string : string;
|
|
46
46
|
/**
|
|
47
|
-
* The runtime report object with all of it's associated methods;
|
|
48
|
-
* of the primary export: `createReporter`
|
|
47
|
+
* The runtime report object with all of it's associated methods;
|
|
48
|
+
* the result of the primary export: `createReporter`
|
|
49
49
|
* @private
|
|
50
50
|
*/
|
|
51
51
|
interface RuntimeReporter<T extends RuntimeReporterMessage> {
|
|
@@ -102,6 +102,10 @@ interface RuntimeReporter<T extends RuntimeReporterMessage> {
|
|
|
102
102
|
*/
|
|
103
103
|
fail<U extends T["code"]>(code: U, ...args: ReporterTokensArgs<T, U>): void;
|
|
104
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* The configuration options for createReporter()
|
|
107
|
+
* @since v0.1.0
|
|
108
|
+
*/
|
|
105
109
|
interface RuntimeReporterOptions {
|
|
106
110
|
/**
|
|
107
111
|
* A hook to format the message text universally. By default, it
|
|
@@ -121,10 +125,11 @@ interface RuntimeReporterOptions {
|
|
|
121
125
|
defaultTemplate?: string;
|
|
122
126
|
}
|
|
123
127
|
/**
|
|
124
|
-
* Creates a reporter object with
|
|
128
|
+
* Creates a new runtime reporter object with all of it's associated methods
|
|
125
129
|
* @param messages The messages record organized by code and template
|
|
126
130
|
* @param options Optional configuration options
|
|
127
131
|
* @returns A runtime report object
|
|
132
|
+
* @since v0.1.0
|
|
128
133
|
*/
|
|
129
134
|
declare function createReporter<T extends RuntimeReporterMessage>(messages: RuntimeReporterMessages<T>, options?: RuntimeReporterOptions): RuntimeReporter<T>;
|
|
130
135
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * The type information for a single runtime reporter message\n * @since v0.1.0\n */\nexport type RuntimeReporterMessage = {\n code: string;\n template: string;\n tokens?: string;\n};\n\n/**\n * The type for a full list of messages with their associated code and template\n * @since v0.1.0\n */\nexport type RuntimeReporterMessages<T extends RuntimeReporterMessage> = {\n [K in T[\"code\"]]: Extract<T, { code: K }>[\"template\"];\n};\n\n/**\n * The type for the supported values of a placeholder token\n * @since v0.1.0\n */\nexport type RuntimeReporterToken = string | number | boolean | Error | null | undefined;\n\n/**\n * The type for a record of placeholder token names and their values\n * @since v0.2.0\n */\nexport type RuntimeReporterTokens = Record<string, RuntimeReporterToken>;\n\n/**\n * A utility type used to determine the second argument of the runtime reporter methods\n * @private\n */\ntype ReporterTokensArgs<T extends RuntimeReporterMessage, U extends T[\"code\"]> = Extract<\n T,\n { code: U }\n>[\"tokens\"] extends infer Tokens\n ? [Tokens] extends [string]\n ? [tokens: Record<Tokens, RuntimeReporterToken>]\n : []\n : [];\n\n/**\n * Return type for message(); displays the template + code in default format on hover.\n * The runtime value is the resolved string (tokens substituted); the type is for DX only.\n * @private\n */\ntype MessageReturnType<T extends RuntimeReporterMessage, U extends T[\"code\"]> =\n Extract<T, { code: U }> extends { template: infer Template }\n ? Template extends string\n ? `${Template} (${U})`\n : string\n : string;\n\n/**\n * The runtime report object with all of it's associated methods; the result\n * of the primary export: `createReporter`\n * @private\n */\ninterface RuntimeReporter<T extends RuntimeReporterMessage> {\n /**\n * Retrieves the full text of the targeted message\n *\n * _Note: As a convenience, the return type will attempt to show the literal type of the template\n * pattern and code suffix (in the default format) for the message on hover; the actual output may\n * vary based on the tokens provided and the `formatMessage` option._\n *\n * _Tip: This method is particularly useful in the test environment; allowing you\n * to make precise assertions without having to duplicate any of the raw message text._\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n message<U extends T[\"code\"]>(\n code: U,\n ...args: ReporterTokensArgs<T, U>\n ): MessageReturnType<T, U>;\n\n /**\n * Logs a warning to the console with the full text of the targeted message in non-production environments\n *\n * _Note: This method will only log when the message associated with the code is found;\n * meaning it will not be called in production if the `createReporter` function\n * is provided an empty message set._\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n warn<U extends T[\"code\"]>(code: U, ...args: ReporterTokensArgs<T, U>): void;\n\n /**\n * Logs an error to the console with the full text of the targeted message in non-production environments\n *\n * _Note: This method will only log when the message associated with the code is found;\n * meaning it will not be called in production if the `createReporter` function\n * is provided an empty message set._\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n error<U extends T[\"code\"]>(code: U, ...args: ReporterTokensArgs<T, U>): void;\n\n /**\n * Logs a message to the console with the full text of the targeted message in non-production environments\n *\n * _Note: This method will only log when the message associated with the code is found;\n * meaning it will not be called in production if the `createReporter` function\n * is provided an empty message set._\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n log<U extends T[\"code\"]>(code: U, ...args: ReporterTokensArgs<T, U>): void;\n\n /**\n * Throws an error with the full text of the targeted message in all environments\n *\n * _Note: When the `createReporter` function is called in production with an empty\n * message set, this method will use the \"defaultTemplate\" option in this format: \"<defaultTemplate> (<code>)\"_\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n fail<U extends T[\"code\"]>(code: U, ...args: ReporterTokensArgs<T, U>): void;\n}\n\nexport interface RuntimeReporterOptions {\n /**\n * A hook to format the message text universally. By default, it\n * outputs the message in the following format: \"<message> (<code>)\"\n * @param message The resolved message text; the placeholders have been replaced by their token values\n * @param code The unique code associated with the message\n * @returns The final, fully formatted message\n */\n formatMessage?: (message: string, code: string) => string;\n\n /**\n * The default template to fallback on when a provided code does not\n * have an associated message. Defaults to \"An error occurred\"\n *\n * _Note: This is only used when the `fail` method is called in production\n * environments when the `createReporter` function is provided an empty message set._\n */\n defaultTemplate?: string;\n}\n\n/**\n * Resolves the message text via the message template and the associated tokens\n * @param template The template string for the reported message\n * @param tokens The token names and values for the instance\n * @returns The resolved message text; returns an empty string if the template is falsy\n */\nconst resolveTemplate = function resolveTemplate(\n template: string,\n tokens?: Record<string, RuntimeReporterToken>\n): string {\n let message = template;\n\n if (message) {\n Object.entries(tokens || {}).forEach((entry) => {\n const [token, value] = entry;\n const replace = value instanceof Error ? value.message : String(value ?? \"\");\n const sanitized = token.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n message = message.replace(new RegExp(`\\\\{\\\\{\\\\s*${sanitized}\\\\s*\\\\}\\\\}`, \"g\"), replace);\n });\n }\n\n return message;\n};\n\n/**\n * Creates a reporter object with various helpful runtime methods\n * @param messages The messages record organized by code and template\n * @param options Optional configuration options\n * @returns A runtime report object\n */\nexport function createReporter<T extends RuntimeReporterMessage>(\n messages: RuntimeReporterMessages<T>,\n options: RuntimeReporterOptions = {}\n): RuntimeReporter<T> {\n const {\n formatMessage = (message, code) => `${message} (${code})`,\n defaultTemplate = \"An error occurred\",\n } = options;\n const messagesByCode = messages as Record<string, string>;\n\n /**\n * Retrieves the final message for a give code and its associated tokens\n * @param code The unique code associated with the message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n * @returns The fully resolve message or an empty string if there was no template\n */\n const getMessage = function getMessage(\n code: string,\n ...args: Array<Record<string, RuntimeReporterToken>>\n ): string {\n const template = messagesByCode[code] || defaultTemplate;\n const tokens = args[0];\n const text = resolveTemplate(template, tokens);\n return formatMessage(text, code);\n };\n\n return {\n message: (code, ...args) =>\n getMessage(code, ...args) as MessageReturnType<T, typeof code & T[\"code\"]>,\n error: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messagesByCode[code]) console.error(message);\n },\n warn: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messagesByCode[code]) console.warn(message);\n },\n log: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messagesByCode[code]) console.log(message);\n },\n fail: (code, ...args) => {\n const message = getMessage(code, ...args);\n throw new Error(message);\n },\n };\n}\n"],"mappings":";AAoJA,IAAM,kBAAkB,SAASA,iBAC7B,UACA,QACM;AACN,MAAI,UAAU;AAEd,MAAI,SAAS;AACT,WAAO,QAAQ,UAAU,CAAC,CAAC,EAAE,QAAQ,CAAC,UAAU;AAC5C,YAAM,CAAC,OAAO,KAAK,IAAI;AACvB,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,SAAS,EAAE;AAC3E,YAAM,YAAY,MAAM,QAAQ,uBAAuB,MAAM;AAC7D,gBAAU,QAAQ,QAAQ,IAAI,OAAO,aAAa,SAAS,cAAc,GAAG,GAAG,OAAO;AAAA,IAC1F,CAAC;AAAA,EACL;AAEA,SAAO;AACX;AAQO,SAAS,eACZ,UACA,UAAkC,CAAC,GACjB;AAClB,QAAM;AAAA,IACF,gBAAgB,CAAC,SAAS,SAAS,GAAG,OAAO,KAAK,IAAI;AAAA,IACtD,kBAAkB;AAAA,EACtB,IAAI;AACJ,QAAM,iBAAiB;AAQvB,QAAM,aAAa,SAASC,YACxB,SACG,MACG;AACN,UAAM,WAAW,eAAe,IAAI,KAAK;AACzC,UAAM,SAAS,KAAK,CAAC;AACrB,UAAM,OAAO,gBAAgB,UAAU,MAAM;AAC7C,WAAO,cAAc,MAAM,IAAI;AAAA,EACnC;AAEA,SAAO;AAAA,IACH,SAAS,CAAC,SAAS,SACf,WAAW,MAAM,GAAG,IAAI;AAAA,IAC5B,OAAO,CAAC,SAAS,SAAS;AACtB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,eAAe,IAAI,EAAG,SAAQ,MAAM,OAAO;AAAA,IACnD;AAAA,IACA,MAAM,CAAC,SAAS,SAAS;AACrB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,eAAe,IAAI,EAAG,SAAQ,KAAK,OAAO;AAAA,IAClD;AAAA,IACA,KAAK,CAAC,SAAS,SAAS;AACpB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,eAAe,IAAI,EAAG,SAAQ,IAAI,OAAO;AAAA,IACjD;AAAA,IACA,MAAM,CAAC,SAAS,SAAS;AACrB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,YAAM,IAAI,MAAM,OAAO;AAAA,IAC3B;AAAA,EACJ;AACJ;","names":["resolveTemplate","getMessage"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * The type information for a single runtime reporter message\n * @since v0.1.0\n */\nexport type RuntimeReporterMessage = {\n code: string;\n template: string;\n tokens?: string;\n};\n\n/**\n * The type for a full list of messages with their associated code and template\n * @since v0.1.0\n */\nexport type RuntimeReporterMessages<T extends RuntimeReporterMessage> = {\n [K in T[\"code\"]]: Extract<T, { code: K }>[\"template\"];\n};\n\n/**\n * The type for the supported values of a placeholder token\n * @since v0.1.0\n */\nexport type RuntimeReporterToken = string | number | boolean | Error | null | undefined;\n\n/**\n * The type for a record of placeholder token names and their values\n * @since v0.2.0\n */\nexport type RuntimeReporterTokens = Record<string, RuntimeReporterToken>;\n\n/**\n * A utility type used to determine the second argument of the runtime reporter methods\n * @private\n */\ntype ReporterTokensArgs<T extends RuntimeReporterMessage, U extends T[\"code\"]> = Extract<\n T,\n { code: U }\n>[\"tokens\"] extends infer Tokens\n ? [Tokens] extends [string]\n ? [tokens: Record<Tokens, RuntimeReporterToken>]\n : []\n : [];\n\n/**\n * Return type for message(); displays the template + code in default format on hover.\n * The runtime value is the resolved string (tokens substituted); the type is for DX only.\n * @private\n */\ntype MessageReturnType<T extends RuntimeReporterMessage, U extends T[\"code\"]> =\n Extract<T, { code: U }> extends { template: infer Template }\n ? Template extends string\n ? `${Template} (${U})`\n : string\n : string;\n\n/**\n * The runtime report object with all of it's associated methods;\n * the result of the primary export: `createReporter`\n * @private\n */\ninterface RuntimeReporter<T extends RuntimeReporterMessage> {\n /**\n * Retrieves the full text of the targeted message\n *\n * _Note: As a convenience, the return type will attempt to show the literal type of the template\n * pattern and code suffix (in the default format) for the message on hover; the actual output may\n * vary based on the tokens provided and the `formatMessage` option._\n *\n * _Tip: This method is particularly useful in the test environment; allowing you\n * to make precise assertions without having to duplicate any of the raw message text._\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n message<U extends T[\"code\"]>(\n code: U,\n ...args: ReporterTokensArgs<T, U>\n ): MessageReturnType<T, U>;\n\n /**\n * Logs a warning to the console with the full text of the targeted message in non-production environments\n *\n * _Note: This method will only log when the message associated with the code is found;\n * meaning it will not be called in production if the `createReporter` function\n * is provided an empty message set._\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n warn<U extends T[\"code\"]>(code: U, ...args: ReporterTokensArgs<T, U>): void;\n\n /**\n * Logs an error to the console with the full text of the targeted message in non-production environments\n *\n * _Note: This method will only log when the message associated with the code is found;\n * meaning it will not be called in production if the `createReporter` function\n * is provided an empty message set._\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n error<U extends T[\"code\"]>(code: U, ...args: ReporterTokensArgs<T, U>): void;\n\n /**\n * Logs a message to the console with the full text of the targeted message in non-production environments\n *\n * _Note: This method will only log when the message associated with the code is found;\n * meaning it will not be called in production if the `createReporter` function\n * is provided an empty message set._\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n log<U extends T[\"code\"]>(code: U, ...args: ReporterTokensArgs<T, U>): void;\n\n /**\n * Throws an error with the full text of the targeted message in all environments\n *\n * _Note: When the `createReporter` function is called in production with an empty\n * message set, this method will use the \"defaultTemplate\" option in this format: \"<defaultTemplate> (<code>)\"_\n * @param code A direct reference to the unique code for the targeted message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n */\n fail<U extends T[\"code\"]>(code: U, ...args: ReporterTokensArgs<T, U>): void;\n}\n\n/**\n * The configuration options for createReporter()\n * @since v0.1.0\n */\nexport interface RuntimeReporterOptions {\n /**\n * A hook to format the message text universally. By default, it\n * outputs the message in the following format: \"<message> (<code>)\"\n * @param message The resolved message text; the placeholders have been replaced by their token values\n * @param code The unique code associated with the message\n * @returns The final, fully formatted message\n */\n formatMessage?: (message: string, code: string) => string;\n\n /**\n * The default template to fallback on when a provided code does not\n * have an associated message. Defaults to \"An error occurred\"\n *\n * _Note: This is only used when the `fail` method is called in production\n * environments when the `createReporter` function is provided an empty message set._\n */\n defaultTemplate?: string;\n}\n\n/**\n * Resolves the message text via the message template and the associated tokens\n * @param template The template string for the reported message\n * @param tokens The token names and values for the instance\n * @returns The resolved message text; returns an empty string if the template is falsy\n * @private\n */\nconst resolveTemplate = function resolveTemplate(\n template: string,\n tokens?: Record<string, RuntimeReporterToken>\n): string {\n let message = template;\n\n if (message) {\n Object.entries(tokens || {}).forEach((entry) => {\n const [token, value] = entry;\n const replace = value instanceof Error ? value.message : String(value ?? \"\");\n const sanitized = token.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n message = message.replace(new RegExp(`\\\\{\\\\{\\\\s*${sanitized}\\\\s*\\\\}\\\\}`, \"g\"), replace);\n });\n }\n\n return message;\n};\n\n/**\n * Creates a new runtime reporter object with all of it's associated methods\n * @param messages The messages record organized by code and template\n * @param options Optional configuration options\n * @returns A runtime report object\n * @since v0.1.0\n */\nexport function createReporter<T extends RuntimeReporterMessage>(\n messages: RuntimeReporterMessages<T>,\n options: RuntimeReporterOptions = {}\n): RuntimeReporter<T> {\n const {\n formatMessage = (message, code) => `${message} (${code})`,\n defaultTemplate = \"An error occurred\",\n } = options;\n const messagesByCode = messages as Record<string, string>;\n\n /**\n * Retrieves the final message for a give code and its associated tokens\n * @param code The unique code associated with the message\n * @param args The remaining optional argument for the function; a record containing the placeholder token values\n * @returns The fully resolve message or an empty string if there was no template\n */\n const getMessage = function getMessage(\n code: string,\n ...args: Array<Record<string, RuntimeReporterToken>>\n ): string {\n const template = messagesByCode[code] || defaultTemplate;\n const tokens = args[0];\n const text = resolveTemplate(template, tokens);\n return formatMessage(text, code);\n };\n\n return {\n message: (code, ...args) =>\n getMessage(code, ...args) as MessageReturnType<T, typeof code & T[\"code\"]>,\n error: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messagesByCode[code]) console.error(message);\n },\n warn: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messagesByCode[code]) console.warn(message);\n },\n log: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messagesByCode[code]) console.log(message);\n },\n fail: (code, ...args) => {\n const message = getMessage(code, ...args);\n throw new Error(message);\n },\n };\n}\n"],"mappings":";AAyJA,IAAM,kBAAkB,SAASA,iBAC7B,UACA,QACM;AACN,MAAI,UAAU;AAEd,MAAI,SAAS;AACT,WAAO,QAAQ,UAAU,CAAC,CAAC,EAAE,QAAQ,CAAC,UAAU;AAC5C,YAAM,CAAC,OAAO,KAAK,IAAI;AACvB,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,SAAS,EAAE;AAC3E,YAAM,YAAY,MAAM,QAAQ,uBAAuB,MAAM;AAC7D,gBAAU,QAAQ,QAAQ,IAAI,OAAO,aAAa,SAAS,cAAc,GAAG,GAAG,OAAO;AAAA,IAC1F,CAAC;AAAA,EACL;AAEA,SAAO;AACX;AASO,SAAS,eACZ,UACA,UAAkC,CAAC,GACjB;AAClB,QAAM;AAAA,IACF,gBAAgB,CAAC,SAAS,SAAS,GAAG,OAAO,KAAK,IAAI;AAAA,IACtD,kBAAkB;AAAA,EACtB,IAAI;AACJ,QAAM,iBAAiB;AAQvB,QAAM,aAAa,SAASC,YACxB,SACG,MACG;AACN,UAAM,WAAW,eAAe,IAAI,KAAK;AACzC,UAAM,SAAS,KAAK,CAAC;AACrB,UAAM,OAAO,gBAAgB,UAAU,MAAM;AAC7C,WAAO,cAAc,MAAM,IAAI;AAAA,EACnC;AAEA,SAAO;AAAA,IACH,SAAS,CAAC,SAAS,SACf,WAAW,MAAM,GAAG,IAAI;AAAA,IAC5B,OAAO,CAAC,SAAS,SAAS;AACtB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,eAAe,IAAI,EAAG,SAAQ,MAAM,OAAO;AAAA,IACnD;AAAA,IACA,MAAM,CAAC,SAAS,SAAS;AACrB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,eAAe,IAAI,EAAG,SAAQ,KAAK,OAAO;AAAA,IAClD;AAAA,IACA,KAAK,CAAC,SAAS,SAAS;AACpB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,eAAe,IAAI,EAAG,SAAQ,IAAI,OAAO;AAAA,IACjD;AAAA,IACA,MAAM,CAAC,SAAS,SAAS;AACrB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,YAAM,IAAI,MAAM,OAAO;AAAA,IAC3B;AAAA,EACJ;AACJ;","names":["resolveTemplate","getMessage"]}
|
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.3",
|
|
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",
|