runtime-reporter 0.4.8 → 0.5.0
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 +72 -11
- package/dist/index.cjs +6 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -2
- package/dist/index.d.ts +26 -2
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -116,8 +116,8 @@ const reporter = createReporter({
|
|
|
116
116
|
ERR01: "{{ componentName }} failed to mount",
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
-
reporter.
|
|
120
|
-
// Logs: "MyComponent failed to mount (ERR01)"
|
|
119
|
+
reporter.error("ERR01", { componentName: "MyComponent" });
|
|
120
|
+
// ✅ Logs: "MyComponent failed to mount (ERR01)"
|
|
121
121
|
```
|
|
122
122
|
|
|
123
123
|
### 3. Development vs. production
|
|
@@ -134,12 +134,12 @@ Development environments get detailed messaging, while production environments g
|
|
|
134
134
|
|
|
135
135
|
```ts
|
|
136
136
|
reporter.error("ERR01");
|
|
137
|
-
// In development, it logs: "Something went wrong (ERR01)"
|
|
138
|
-
// In production, it does not log
|
|
137
|
+
// ✅ In development, it logs: "Something went wrong (ERR01)"
|
|
138
|
+
// ✅ In production, it does not log
|
|
139
139
|
|
|
140
140
|
reporter.fail("ERR01");
|
|
141
|
-
// In development, it throws: "Something went wrong (ERR01)"
|
|
142
|
-
// In production, it throws: "An error occurred (ERR01)"
|
|
141
|
+
// ✅ In development, it throws: "Something went wrong (ERR01)"
|
|
142
|
+
// ✅ In production, it throws: "An error occurred (ERR01)"
|
|
143
143
|
```
|
|
144
144
|
|
|
145
145
|
### 4. Type safety
|
|
@@ -180,10 +180,34 @@ it("should log error if component fails to mount", () => {
|
|
|
180
180
|
|
|
181
181
|
expect(console.error).toHaveBeenCalledWith(
|
|
182
182
|
reporter.message("ERR01", { componentName: "MyComponent" })
|
|
183
|
+
// ✅ Asserts: "MyComponent failed to mount (ERR01)"
|
|
183
184
|
);
|
|
184
185
|
});
|
|
185
186
|
```
|
|
186
187
|
|
|
188
|
+
### 6. Custom side effects
|
|
189
|
+
|
|
190
|
+
Leverage the `onReport` hook to perform custom actions (e.g., logging to remote services) when a report is made.
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
const reporter = createReporter(messages, {
|
|
194
|
+
onReport: (payload) => {
|
|
195
|
+
fetch("/api/reports", {
|
|
196
|
+
method: "POST",
|
|
197
|
+
body: JSON.stringify(payload),
|
|
198
|
+
});
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
reporter.error("ERR01");
|
|
203
|
+
// ✅ Sends a POST request with the following payload:
|
|
204
|
+
// {
|
|
205
|
+
// code: "ERR01",
|
|
206
|
+
// message: "MyComponent failed to mount (ERR01)",
|
|
207
|
+
// level: "error",
|
|
208
|
+
// }
|
|
209
|
+
```
|
|
210
|
+
|
|
187
211
|
## API
|
|
188
212
|
|
|
189
213
|
### `createReporter(RuntimeReporterMessages, options?: RuntimeReporterOptions): RuntimeReporter`
|
|
@@ -202,10 +226,11 @@ Takes a messages object, an optional set of configuration options, and returns a
|
|
|
202
226
|
|
|
203
227
|
### `RuntimeReporterOptions`
|
|
204
228
|
|
|
205
|
-
| Property | Type
|
|
206
|
-
| --------------- |
|
|
207
|
-
| formatMessage | `(message: string, code: string) => string`
|
|
208
|
-
| defaultTemplate | `string`
|
|
229
|
+
| Property | Type | Required | Description |
|
|
230
|
+
| --------------- | ------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
231
|
+
| formatMessage | `(message: string, code: string) => string` | No | Customize the final output of every message. By default, messages are in the format: `"<message> (<code>)"`. |
|
|
232
|
+
| defaultTemplate | `string` | No | Fallback message text used when the code does not exist in `messages`. Defaults to `"An error occurred"`. This is mostly relevant for `fail()` in production when you pass an empty message set. |
|
|
233
|
+
| onReport | `(payload: RuntimeReporterReportPayload) => void` | No | A hook to perform custom actions when a report is made via `error`, `warn`, `log`, or `fail`. |
|
|
209
234
|
|
|
210
235
|
### `RuntimeReporterTokens`
|
|
211
236
|
|
|
@@ -213,6 +238,14 @@ Takes a messages object, an optional set of configuration options, and returns a
|
|
|
213
238
|
| -------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
214
239
|
| `string` | `RuntimeReporterToken` | A record of token names along with their replacement value. Supported types include: `string`, `number`, `boolean`, `Error`. |
|
|
215
240
|
|
|
241
|
+
### `RuntimeReporterReportPayload`
|
|
242
|
+
|
|
243
|
+
| Property | Type | Description |
|
|
244
|
+
| --------- | -------- | ------------------------------------------------------------------------------------- | ----- | ------- | --------------------------------- |
|
|
245
|
+
| `code` | `string` | The unique code associated with the message. |
|
|
246
|
+
| `message` | `string` | The resolved message text; the placeholders have been replaced by their token values. |
|
|
247
|
+
| `level` | `"error" | "warn" | "log" | "fail"` | The severity level of the report. |
|
|
248
|
+
|
|
216
249
|
## Examples
|
|
217
250
|
|
|
218
251
|
### Custom formatting
|
|
@@ -221,7 +254,7 @@ You can customize the format of the message by providing a custom `formatMessage
|
|
|
221
254
|
|
|
222
255
|
```ts
|
|
223
256
|
const reporter = createReporter(messages, {
|
|
224
|
-
formatMessage: (
|
|
257
|
+
formatMessage: (message, code) => `[${code}] ${message}`,
|
|
225
258
|
});
|
|
226
259
|
|
|
227
260
|
reporter.message("ERR01", { componentName: "MyComponent" });
|
|
@@ -257,6 +290,34 @@ it("should log error if component fails to mount", () => {
|
|
|
257
290
|
});
|
|
258
291
|
```
|
|
259
292
|
|
|
293
|
+
### Using `onReport` and `formatMessage` together
|
|
294
|
+
|
|
295
|
+
By combining the `onReport` and `formatMessage` options, you can have granular control over the message output and reporting behavior. For example, you could log a generic message to users while still sending the full payload to a remote service in production environments. At the same time, you can log the full message in non-production environments for debugging purposes.
|
|
296
|
+
|
|
297
|
+
```ts
|
|
298
|
+
const reporter = createReporter(messages, {
|
|
299
|
+
formatMessage: (message, code) => {
|
|
300
|
+
if (process.env.NODE_ENV === "production") {
|
|
301
|
+
return "Generic error message ...";
|
|
302
|
+
} else {
|
|
303
|
+
return `${message} (${code})`;
|
|
304
|
+
}
|
|
305
|
+
},
|
|
306
|
+
onReport: (payload) => {
|
|
307
|
+
if (process.env.NODE_ENV === "production") {
|
|
308
|
+
fetch("/api/reports", {
|
|
309
|
+
method: "POST",
|
|
310
|
+
body: JSON.stringify(payload),
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
reporter.error("ERR01");
|
|
317
|
+
// ✅ In production, users get a generic message AND remote service gets the full message
|
|
318
|
+
// ✅ In non-production, developers get the full message
|
|
319
|
+
```
|
|
320
|
+
|
|
260
321
|
### Type safety without TypeScript
|
|
261
322
|
|
|
262
323
|
You can still get the same benefits as TypeScript by using JSDoc-style type annotations.
|
package/dist/index.cjs
CHANGED
|
@@ -38,7 +38,8 @@ var resolveTemplate = function resolveTemplate2(template, tokens) {
|
|
|
38
38
|
function createReporter(messages, options = {}) {
|
|
39
39
|
const {
|
|
40
40
|
formatMessage = (message, code) => `${message} (${code})`,
|
|
41
|
-
defaultTemplate = "An error occurred"
|
|
41
|
+
defaultTemplate = "An error occurred",
|
|
42
|
+
onReport
|
|
42
43
|
} = options;
|
|
43
44
|
const messagesByCode = messages;
|
|
44
45
|
const getMessage = function getMessage2(code, ...args) {
|
|
@@ -51,18 +52,22 @@ function createReporter(messages, options = {}) {
|
|
|
51
52
|
message: (code, ...args) => getMessage(code, ...args),
|
|
52
53
|
error: (code, ...args) => {
|
|
53
54
|
const message = getMessage(code, ...args);
|
|
55
|
+
if (onReport) onReport({ code, message, level: "error" });
|
|
54
56
|
if (messagesByCode[code]) console.error(message);
|
|
55
57
|
},
|
|
56
58
|
warn: (code, ...args) => {
|
|
57
59
|
const message = getMessage(code, ...args);
|
|
60
|
+
if (onReport) onReport({ code, message, level: "warn" });
|
|
58
61
|
if (messagesByCode[code]) console.warn(message);
|
|
59
62
|
},
|
|
60
63
|
log: (code, ...args) => {
|
|
61
64
|
const message = getMessage(code, ...args);
|
|
65
|
+
if (onReport) onReport({ code, message, level: "log" });
|
|
62
66
|
if (messagesByCode[code]) console.log(message);
|
|
63
67
|
},
|
|
64
68
|
fail: (code, ...args) => {
|
|
65
69
|
const message = getMessage(code, ...args);
|
|
70
|
+
if (onReport) onReport({ code, message, level: "fail" });
|
|
66
71
|
throw new Error(message);
|
|
67
72
|
}
|
|
68
73
|
};
|
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;\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>): never;\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"]}
|
|
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>): never;\n}\n\n/**\n * The payload for the onReport hook\n */\nexport type RuntimeReporterReportPayload = {\n /**\n * The unique code associated with the message\n */\n code: string;\n\n /**\n * The resolved message text; the placeholders have been replaced by their token values\n */\n message: string;\n\n /**\n * The severity level of the report\n */\n level: \"error\" | \"warn\" | \"log\" | \"fail\";\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 that is logged to the console. 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 * A hook to perform custom actions when any of the report methods (minus the\n * `message` method) are called. This is useful for logging to a remote service,\n * or for performing other actions based on the report.\n * @param payload The payload for the report\n */\n onReport?: (payload: RuntimeReporterReportPayload) => void;\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 onReport,\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 (onReport) onReport({ code, message, level: \"error\" });\n if (messagesByCode[code]) console.error(message);\n },\n warn: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (onReport) onReport({ code, message, level: \"warn\" });\n if (messagesByCode[code]) console.warn(message);\n },\n log: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (onReport) onReport({ code, message, level: \"log\" });\n if (messagesByCode[code]) console.log(message);\n },\n fail: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (onReport) onReport({ code, message, level: \"fail\" });\n throw new Error(message);\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAqLA,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,IAClB;AAAA,EACJ,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,SAAU,UAAS,EAAE,MAAM,SAAS,OAAO,QAAQ,CAAC;AACxD,UAAI,eAAe,IAAI,EAAG,SAAQ,MAAM,OAAO;AAAA,IACnD;AAAA,IACA,MAAM,CAAC,SAAS,SAAS;AACrB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,SAAU,UAAS,EAAE,MAAM,SAAS,OAAO,OAAO,CAAC;AACvD,UAAI,eAAe,IAAI,EAAG,SAAQ,KAAK,OAAO;AAAA,IAClD;AAAA,IACA,KAAK,CAAC,SAAS,SAAS;AACpB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,SAAU,UAAS,EAAE,MAAM,SAAS,OAAO,MAAM,CAAC;AACtD,UAAI,eAAe,IAAI,EAAG,SAAQ,IAAI,OAAO;AAAA,IACjD;AAAA,IACA,MAAM,CAAC,SAAS,SAAS;AACrB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,SAAU,UAAS,EAAE,MAAM,SAAS,OAAO,OAAO,CAAC;AACvD,YAAM,IAAI,MAAM,OAAO;AAAA,IAC3B;AAAA,EACJ;AACJ;","names":["resolveTemplate","getMessage"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -102,13 +102,30 @@ interface RuntimeReporter<T extends RuntimeReporterMessage> {
|
|
|
102
102
|
*/
|
|
103
103
|
fail<U extends T["code"]>(code: U, ...args: ReporterTokensArgs<T, U>): never;
|
|
104
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* The payload for the onReport hook
|
|
107
|
+
*/
|
|
108
|
+
type RuntimeReporterReportPayload = {
|
|
109
|
+
/**
|
|
110
|
+
* The unique code associated with the message
|
|
111
|
+
*/
|
|
112
|
+
code: string;
|
|
113
|
+
/**
|
|
114
|
+
* The resolved message text; the placeholders have been replaced by their token values
|
|
115
|
+
*/
|
|
116
|
+
message: string;
|
|
117
|
+
/**
|
|
118
|
+
* The severity level of the report
|
|
119
|
+
*/
|
|
120
|
+
level: "error" | "warn" | "log" | "fail";
|
|
121
|
+
};
|
|
105
122
|
/**
|
|
106
123
|
* The configuration options for createReporter()
|
|
107
124
|
* @since v0.1.0
|
|
108
125
|
*/
|
|
109
126
|
interface RuntimeReporterOptions {
|
|
110
127
|
/**
|
|
111
|
-
* A hook to format the message text
|
|
128
|
+
* A hook to format the message text that is logged to the console. By default, it
|
|
112
129
|
* outputs the message in the following format: "<message> (<code>)"
|
|
113
130
|
* @param message The resolved message text; the placeholders have been replaced by their token values
|
|
114
131
|
* @param code The unique code associated with the message
|
|
@@ -123,6 +140,13 @@ interface RuntimeReporterOptions {
|
|
|
123
140
|
* environments when the `createReporter` function is provided an empty message set._
|
|
124
141
|
*/
|
|
125
142
|
defaultTemplate?: string;
|
|
143
|
+
/**
|
|
144
|
+
* A hook to perform custom actions when any of the report methods (minus the
|
|
145
|
+
* `message` method) are called. This is useful for logging to a remote service,
|
|
146
|
+
* or for performing other actions based on the report.
|
|
147
|
+
* @param payload The payload for the report
|
|
148
|
+
*/
|
|
149
|
+
onReport?: (payload: RuntimeReporterReportPayload) => void;
|
|
126
150
|
}
|
|
127
151
|
/**
|
|
128
152
|
* Creates a new runtime reporter object with all of it's associated methods
|
|
@@ -133,4 +157,4 @@ interface RuntimeReporterOptions {
|
|
|
133
157
|
*/
|
|
134
158
|
declare function createReporter<T extends RuntimeReporterMessage>(messages: RuntimeReporterMessages<T>, options?: RuntimeReporterOptions): RuntimeReporter<T>;
|
|
135
159
|
|
|
136
|
-
export { type RuntimeReporterMessage, type RuntimeReporterMessages, type RuntimeReporterOptions, type RuntimeReporterToken, type RuntimeReporterTokens, createReporter };
|
|
160
|
+
export { type RuntimeReporterMessage, type RuntimeReporterMessages, type RuntimeReporterOptions, type RuntimeReporterReportPayload, type RuntimeReporterToken, type RuntimeReporterTokens, createReporter };
|
package/dist/index.d.ts
CHANGED
|
@@ -102,13 +102,30 @@ interface RuntimeReporter<T extends RuntimeReporterMessage> {
|
|
|
102
102
|
*/
|
|
103
103
|
fail<U extends T["code"]>(code: U, ...args: ReporterTokensArgs<T, U>): never;
|
|
104
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* The payload for the onReport hook
|
|
107
|
+
*/
|
|
108
|
+
type RuntimeReporterReportPayload = {
|
|
109
|
+
/**
|
|
110
|
+
* The unique code associated with the message
|
|
111
|
+
*/
|
|
112
|
+
code: string;
|
|
113
|
+
/**
|
|
114
|
+
* The resolved message text; the placeholders have been replaced by their token values
|
|
115
|
+
*/
|
|
116
|
+
message: string;
|
|
117
|
+
/**
|
|
118
|
+
* The severity level of the report
|
|
119
|
+
*/
|
|
120
|
+
level: "error" | "warn" | "log" | "fail";
|
|
121
|
+
};
|
|
105
122
|
/**
|
|
106
123
|
* The configuration options for createReporter()
|
|
107
124
|
* @since v0.1.0
|
|
108
125
|
*/
|
|
109
126
|
interface RuntimeReporterOptions {
|
|
110
127
|
/**
|
|
111
|
-
* A hook to format the message text
|
|
128
|
+
* A hook to format the message text that is logged to the console. By default, it
|
|
112
129
|
* outputs the message in the following format: "<message> (<code>)"
|
|
113
130
|
* @param message The resolved message text; the placeholders have been replaced by their token values
|
|
114
131
|
* @param code The unique code associated with the message
|
|
@@ -123,6 +140,13 @@ interface RuntimeReporterOptions {
|
|
|
123
140
|
* environments when the `createReporter` function is provided an empty message set._
|
|
124
141
|
*/
|
|
125
142
|
defaultTemplate?: string;
|
|
143
|
+
/**
|
|
144
|
+
* A hook to perform custom actions when any of the report methods (minus the
|
|
145
|
+
* `message` method) are called. This is useful for logging to a remote service,
|
|
146
|
+
* or for performing other actions based on the report.
|
|
147
|
+
* @param payload The payload for the report
|
|
148
|
+
*/
|
|
149
|
+
onReport?: (payload: RuntimeReporterReportPayload) => void;
|
|
126
150
|
}
|
|
127
151
|
/**
|
|
128
152
|
* Creates a new runtime reporter object with all of it's associated methods
|
|
@@ -133,4 +157,4 @@ interface RuntimeReporterOptions {
|
|
|
133
157
|
*/
|
|
134
158
|
declare function createReporter<T extends RuntimeReporterMessage>(messages: RuntimeReporterMessages<T>, options?: RuntimeReporterOptions): RuntimeReporter<T>;
|
|
135
159
|
|
|
136
|
-
export { type RuntimeReporterMessage, type RuntimeReporterMessages, type RuntimeReporterOptions, type RuntimeReporterToken, type RuntimeReporterTokens, createReporter };
|
|
160
|
+
export { type RuntimeReporterMessage, type RuntimeReporterMessages, type RuntimeReporterOptions, type RuntimeReporterReportPayload, type RuntimeReporterToken, type RuntimeReporterTokens, createReporter };
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,8 @@ var resolveTemplate = function resolveTemplate2(template, tokens) {
|
|
|
14
14
|
function createReporter(messages, options = {}) {
|
|
15
15
|
const {
|
|
16
16
|
formatMessage = (message, code) => `${message} (${code})`,
|
|
17
|
-
defaultTemplate = "An error occurred"
|
|
17
|
+
defaultTemplate = "An error occurred",
|
|
18
|
+
onReport
|
|
18
19
|
} = options;
|
|
19
20
|
const messagesByCode = messages;
|
|
20
21
|
const getMessage = function getMessage2(code, ...args) {
|
|
@@ -27,18 +28,22 @@ function createReporter(messages, options = {}) {
|
|
|
27
28
|
message: (code, ...args) => getMessage(code, ...args),
|
|
28
29
|
error: (code, ...args) => {
|
|
29
30
|
const message = getMessage(code, ...args);
|
|
31
|
+
if (onReport) onReport({ code, message, level: "error" });
|
|
30
32
|
if (messagesByCode[code]) console.error(message);
|
|
31
33
|
},
|
|
32
34
|
warn: (code, ...args) => {
|
|
33
35
|
const message = getMessage(code, ...args);
|
|
36
|
+
if (onReport) onReport({ code, message, level: "warn" });
|
|
34
37
|
if (messagesByCode[code]) console.warn(message);
|
|
35
38
|
},
|
|
36
39
|
log: (code, ...args) => {
|
|
37
40
|
const message = getMessage(code, ...args);
|
|
41
|
+
if (onReport) onReport({ code, message, level: "log" });
|
|
38
42
|
if (messagesByCode[code]) console.log(message);
|
|
39
43
|
},
|
|
40
44
|
fail: (code, ...args) => {
|
|
41
45
|
const message = getMessage(code, ...args);
|
|
46
|
+
if (onReport) onReport({ code, message, level: "fail" });
|
|
42
47
|
throw new Error(message);
|
|
43
48
|
}
|
|
44
49
|
};
|
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;\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>): never;\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"]}
|
|
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>): never;\n}\n\n/**\n * The payload for the onReport hook\n */\nexport type RuntimeReporterReportPayload = {\n /**\n * The unique code associated with the message\n */\n code: string;\n\n /**\n * The resolved message text; the placeholders have been replaced by their token values\n */\n message: string;\n\n /**\n * The severity level of the report\n */\n level: \"error\" | \"warn\" | \"log\" | \"fail\";\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 that is logged to the console. 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 * A hook to perform custom actions when any of the report methods (minus the\n * `message` method) are called. This is useful for logging to a remote service,\n * or for performing other actions based on the report.\n * @param payload The payload for the report\n */\n onReport?: (payload: RuntimeReporterReportPayload) => void;\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 onReport,\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 (onReport) onReport({ code, message, level: \"error\" });\n if (messagesByCode[code]) console.error(message);\n },\n warn: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (onReport) onReport({ code, message, level: \"warn\" });\n if (messagesByCode[code]) console.warn(message);\n },\n log: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (onReport) onReport({ code, message, level: \"log\" });\n if (messagesByCode[code]) console.log(message);\n },\n fail: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (onReport) onReport({ code, message, level: \"fail\" });\n throw new Error(message);\n },\n };\n}\n"],"mappings":";AAqLA,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,IAClB;AAAA,EACJ,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,SAAU,UAAS,EAAE,MAAM,SAAS,OAAO,QAAQ,CAAC;AACxD,UAAI,eAAe,IAAI,EAAG,SAAQ,MAAM,OAAO;AAAA,IACnD;AAAA,IACA,MAAM,CAAC,SAAS,SAAS;AACrB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,SAAU,UAAS,EAAE,MAAM,SAAS,OAAO,OAAO,CAAC;AACvD,UAAI,eAAe,IAAI,EAAG,SAAQ,KAAK,OAAO;AAAA,IAClD;AAAA,IACA,KAAK,CAAC,SAAS,SAAS;AACpB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,SAAU,UAAS,EAAE,MAAM,SAAS,OAAO,MAAM,CAAC;AACtD,UAAI,eAAe,IAAI,EAAG,SAAQ,IAAI,OAAO;AAAA,IACjD;AAAA,IACA,MAAM,CAAC,SAAS,SAAS;AACrB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,SAAU,UAAS,EAAE,MAAM,SAAS,OAAO,OAAO,CAAC;AACvD,YAAM,IAAI,MAAM,OAAO;AAAA,IAC3B;AAAA,EACJ;AACJ;","names":["resolveTemplate","getMessage"]}
|