runtime-reporter 0.1.0 → 0.3.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 CHANGED
@@ -1,44 +1,147 @@
1
1
  # Runtime Reporter
2
2
 
3
- Runtime messaging that is convenient in development and secure in production
4
- A lightweight runtime messaging solution that's helpful in dev, secure in production
3
+ Structured runtime events for applications and frameworks. A composable foundation for logging, messaging, and runtime reporting.
5
4
 
6
- ### Usage
5
+ ## Features
7
6
 
8
- 1. Define your messages
7
+ - **Security focused**: Pass an empty message set in production to avoid exposing internal messaging.
8
+ - **Centralized messages**: Define message text once; reference by a unique code everywhere else.
9
+ - **Tokenized templates**: Apply runtime data to messages via templated strings and tokenized variables.
10
+ - **Type-safe**: Autocomplete and compile-time validation for message codes and token names.
11
+ - **Tree-shakeable**: Pass an empty message set in production to reduce your bundle size
12
+ - **Test friendly**: Use `message()` to assert on final output without duplicating message text.
13
+ - **Code-based messaging**: Coded messages make it easy to identify errors to perform debugging tasks.
14
+ - **Small footprint**: Minimal bundle size (~2 KB minified) so it adds negligible weight to your app.
15
+ - **Zero dependencies**: No runtime dependencies; the published package is fully self-contained.
16
+ - **Scalable pattern**: Can scale to fit your specific needs regardless of your project's size.
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install runtime-reporter
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ### 1) Define your messages
27
+
28
+ Define the message “schema” (code + template + tokens), then create a `messages` record keyed by the codes.
9
29
 
10
30
  ```ts
11
- import { RuntimeReporterMessages } from "runtime-reporter";
31
+ import type { RuntimeReporterMessages } from "runtime-reporter";
12
32
 
13
- type RuntimeMessages = Array<{
14
- code: "ERR01";
15
- template: "{{ componentName }} An error occured ...";
16
- tokens: ["componentName"];
17
- }>;
33
+ type MyMessages =
34
+ | {
35
+ code: "ERR01";
36
+ template: "{{ componentName }} failed to mount";
37
+ tokens: ["componentName"];
38
+ }
39
+ | {
40
+ code: "INFO01";
41
+ template: "Ready";
42
+ tokens?: undefined;
43
+ };
18
44
 
19
- const messages: RuntimeReporterMessages<RuntimeMessages> = {
20
- ERR01: "{{ componentName }} An error occured ...",
45
+ const messages: RuntimeReporterMessages<MyMessages> = {
46
+ ERR01: "{{ componentName }} failed to mount",
47
+ INFO01: "Ready",
21
48
  };
22
49
  ```
23
50
 
24
- 2. Create the reporter
51
+ ### 2) Create the reporter
25
52
 
26
- Create a reporter instance by passing your messages object and optional configuration. In production builds, pass an empty array to enable tree-shaking and remove all message text from your bundle. The optional `scope` parameter prefixes message codes for easier identification (e.g., `MyApp(ERR01)` instead of `(ERR01)`).
53
+ Pass your messages to `createReporter()` to create a reporter instance.
27
54
 
28
55
  ```ts
29
- import { createRuntimeReporter } = 'runtime-reporter';
56
+ import { createReporter } from "runtime-reporter";
30
57
 
31
- const reporter = createRuntimeReporter(
32
- process.env.NODE_ENV !== 'production' ? messages : ([] as RuntimeMessages)
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
33
61
  );
34
-
35
- export default reporter;
36
62
  ```
37
63
 
38
- 3. Call the reporter methods in your project
64
+ ### 3) Use the reporter
39
65
 
40
- ```js
41
- import reporter from "../my-runtime-reporter";
66
+ Call the various reporter methods wherever you need them.
42
67
 
68
+ ```ts
43
69
  reporter.error("ERR01", { componentName: "MyComponent" });
70
+ // logs: "MyComponent failed to mount (ERR01)"
71
+
72
+ reporter.message("INFO01");
73
+ // returns: "Ready (INFO01)"
74
+ ```
75
+
76
+ ## API
77
+
78
+ ### `createReporter(RuntimeReporterMessages, options?: RuntimeReporterOptions): RuntimeReporter`
79
+
80
+ Takes a list of messages, an optional set of configuration options, and returns a reporter object.
81
+
82
+ ### `RuntimeReporter`
83
+
84
+ | Method | Type | Description |
85
+ | ------- | ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
86
+ | message | `(code: string, tokens:? RuntimeReporterTokens) => string` | Returns the resolved message (no logging); useful for testing environments. |
87
+ | warn | `(code: string, tokens:? RuntimeReporterTokens) => void` | Logs via `console.warn` **only if** the template exists in `messages`. |
88
+ | error | `(code: string, tokens:? RuntimeReporterTokens) => void` | Logs via `console.error` **only if** the template exists in `messages`. |
89
+ | log | `(code: string, tokens:? RuntimeReporterTokens) => void` | Logs via `console.log` **only if** the template exists in `messages`. |
90
+ | fail | `(code: string, tokens:? RuntimeReporterTokens) => never` | Throws `new Error(resolvedMessage)` in **all** environments. Uses the `defaultTemplate` when the template does not exist in `messages`. |
91
+
92
+ ### `RuntimeReporterOptions`
93
+
94
+ | Property | Type | Required | Description |
95
+ | --------------- | ------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
96
+ | formatMessage | `(message: string, code: string) => string` | No | Customize the final output of every message. By default, messages are in the format: `"<message> (<code>)"`. |
97
+ | 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. |
98
+
99
+ ### `RuntimeReporterTokens`
100
+
101
+ | Property | Type | Description |
102
+ | -------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
103
+ | `string` | `RuntimeReporterToken` | A record of token names along with their replacement value. Supported types include: `string`, `number`, `boolean`, `Error`. |
104
+
105
+ ## Examples
106
+
107
+ ### Custom formatting
108
+
109
+ You can customize the format of the message by providing a custom `formatMessage` function.
110
+
111
+ ```ts
112
+ const reporter = createReporter(messages, {
113
+ formatMessage: (msg, code) => `[${code}] ${msg}`,
114
+ });
115
+
116
+ reporter.message("INFO01");
117
+ // "[INFO01] Ready"
118
+ ```
119
+
120
+ ### Using `message()` in tests
121
+
122
+ The `message` method returns the resolved string without side effects, allowing you to validate precise messaging without duplicating text.
123
+
124
+ ```ts
125
+ import { describe, it, expect, vi } from "vitest";
126
+ import { reporter } from "./reporter";
127
+
128
+ describe("reporter messages", () => {
129
+ it("consoles error ERR01 correctly", () => {
130
+ vi.spyOn(console, "error").mockImplementation(() => {});
131
+ reporter.error("ERR01", { componentName: "Widget" });
132
+
133
+ expect(console.error).toHaveBeenCalledWith(
134
+ reporter.message("ERR01", { componentName: "Widget" })
135
+ );
136
+ });
137
+ });
138
+ ```
139
+
140
+ ### CommonJS support
141
+
142
+ If needed, Common JS imports are also available.
143
+
144
+ ```js
145
+ // CJS
146
+ const { createReporter } = require("runtime-reporter");
44
147
  ```
package/dist/index.cjs CHANGED
@@ -17,10 +17,10 @@ var __copyProps = (to, from, except, desc) => {
17
17
  };
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
 
20
- // index.ts
20
+ // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
- createRuntimeReporter: () => createRuntimeReporter
23
+ createReporter: () => createReporter
24
24
  });
25
25
  module.exports = __toCommonJS(index_exports);
26
26
  var resolveTemplate = function resolveTemplate2(template, tokens) {
@@ -29,13 +29,13 @@ var resolveTemplate = function resolveTemplate2(template, tokens) {
29
29
  Object.entries(tokens || {}).forEach((entry) => {
30
30
  const [token, value] = entry;
31
31
  const replace = value instanceof Error ? value.message : String(value ?? "");
32
- const santized = token.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
33
- message = message.replace(new RegExp(`\\{\\{\\s*${santized}\\s*\\}\\}`, "g"), replace);
32
+ const sanitized = token.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
33
+ message = message.replace(new RegExp(`\\{\\{\\s*${sanitized}\\s*\\}\\}`, "g"), replace);
34
34
  });
35
35
  }
36
36
  return message;
37
37
  };
38
- function createRuntimeReporter(messages, options = {}) {
38
+ function createReporter(messages, options = {}) {
39
39
  const {
40
40
  formatMessage = (message, code) => `${message} (${code})`,
41
41
  defaultTemplate = "An error occurred"
@@ -70,6 +70,6 @@ function createRuntimeReporter(messages, options = {}) {
70
70
  }
71
71
  // Annotate the CommonJS export names for ESM import in node:
72
72
  0 && (module.exports = {
73
- createRuntimeReporter
73
+ createReporter
74
74
  });
75
75
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../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[number][\"code\"]]: Extract<T[number], { 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 * A utility type used to determine the second argument of the runtime reporter methods\n * @private\n */\ntype RuntimeReporterTokensArgs<\n T extends RuntimeReporterMessages<RuntimeReporterMessage[]>,\n U extends keyof T,\n> =\n T extends RuntimeReporterMessages<infer V extends RuntimeReporterMessage[]>\n ? Extract<V[number], { code: U }>[\"tokens\"] extends infer Tokens\n ? Tokens extends readonly string[]\n ? [tokens: Record<Tokens[number], RuntimeReporterToken>]\n : []\n : []\n : never;\n\n/**\n * The runtime report object with all of it's associated methods; the result\n * of the primary export: `createRuntimeReporter`\n * @private\n */\ninterface RuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessage[]>> {\n /**\n * Retrieves the full text of the targeted message\n *\n * _Tip: This method is particularly useful in the test environment; allowing you\n * to make precise assertions without having to duplicate an 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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): string;\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 `createRuntimeReporter` function\n * is provided an empty array._\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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): 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 `createRuntimeReporter` function\n * is provided an empty array._\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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): 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 `createRuntimeReporter` function\n * is provided an empty array._\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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): void;\n\n /**\n * Throws an error with the full text of the targeted message in all environments\n *\n * _Note: When the `createRuntimeReporter` function is called in production with an empty\n * array, 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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): void;\n}\n\nexport interface RuntimeReporterOptions {\n /**\n * A hook to format the message text univerally. 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 `createRuntimeReporter` function is provided an empty array._\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 santized = token.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n message = message.replace(new RegExp(`\\\\{\\\\{\\\\s*${santized}\\\\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 createRuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessage[]>>(\n messages: T,\n options: RuntimeReporterOptions = {}\n): RuntimeReporter<T> {\n const {\n formatMessage = (message, code) => `${message} (${code})`,\n defaultTemplate = \"An error occurred\",\n } = options;\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 = messages[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 return getMessage(code, ...args);\n },\n error: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messages[code]) console.error(message);\n },\n warn: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messages[code]) console.warn(message);\n },\n log: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messages[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;AA6IA,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,WAAW,MAAM,QAAQ,uBAAuB,MAAM;AAC5D,gBAAU,QAAQ,QAAQ,IAAI,OAAO,aAAa,QAAQ,cAAc,GAAG,GAAG,OAAO;AAAA,IACzF,CAAC;AAAA,EACL;AAEA,SAAO;AACX;AAQO,SAAS,sBACZ,UACA,UAAkC,CAAC,GACjB;AAClB,QAAM;AAAA,IACF,gBAAgB,CAAC,SAAS,SAAS,GAAG,OAAO,KAAK,IAAI;AAAA,IACtD,kBAAkB;AAAA,EACtB,IAAI;AAQJ,QAAM,aAAa,SAASC,YACxB,SACG,MACG;AACN,UAAM,WAAW,SAAS,IAAI,KAAK;AACnC,UAAM,SAAS,KAAK,CAAC;AACrB,UAAM,OAAO,gBAAgB,UAAU,MAAM;AAC7C,WAAO,cAAc,MAAM,IAAI;AAAA,EACnC;AAEA,SAAO;AAAA,IACH,SAAS,CAAC,SAAS,SAAS;AACxB,aAAO,WAAW,MAAM,GAAG,IAAI;AAAA,IACnC;AAAA,IACA,OAAO,CAAC,SAAS,SAAS;AACtB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,SAAS,IAAI,EAAG,SAAQ,MAAM,OAAO;AAAA,IAC7C;AAAA,IACA,MAAM,CAAC,SAAS,SAAS;AACrB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,SAAS,IAAI,EAAG,SAAQ,KAAK,OAAO;AAAA,IAC5C;AAAA,IACA,KAAK,CAAC,SAAS,SAAS;AACpB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,SAAS,IAAI,EAAG,SAAQ,IAAI,OAAO;AAAA,IAC3C;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 RuntimeReporterTokensArgs<\n T extends RuntimeReporterMessages<RuntimeReporterMessage>,\n U extends keyof T,\n> =\n T extends RuntimeReporterMessages<infer V extends RuntimeReporterMessage>\n ? Extract<V, { code: U }>[\"tokens\"] extends infer Tokens\n ? Tokens extends readonly string[]\n ? [tokens: Record<Tokens[number], RuntimeReporterToken>]\n : []\n : []\n : never;\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 RuntimeReporterMessages<RuntimeReporterMessage>> {\n /**\n * Retrieves the full text of the targeted message\n *\n * _Tip: This method is particularly useful in the test environment; allowing you\n * to make precise assertions without having to duplicate an 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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): string;\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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): 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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): 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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): 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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): 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 RuntimeReporterMessages<RuntimeReporterMessage>>(\n messages: T,\n options: RuntimeReporterOptions = {}\n): RuntimeReporter<T> {\n const {\n formatMessage = (message, code) => `${message} (${code})`,\n defaultTemplate = \"An error occurred\",\n } = options;\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 = messages[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 return getMessage(code, ...args);\n },\n error: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messages[code]) console.error(message);\n },\n warn: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messages[code]) console.warn(message);\n },\n log: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messages[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;AAmJA,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;AAQJ,QAAM,aAAa,SAASC,YACxB,SACG,MACG;AACN,UAAM,WAAW,SAAS,IAAI,KAAK;AACnC,UAAM,SAAS,KAAK,CAAC;AACrB,UAAM,OAAO,gBAAgB,UAAU,MAAM;AAC7C,WAAO,cAAc,MAAM,IAAI;AAAA,EACnC;AAEA,SAAO;AAAA,IACH,SAAS,CAAC,SAAS,SAAS;AACxB,aAAO,WAAW,MAAM,GAAG,IAAI;AAAA,IACnC;AAAA,IACA,OAAO,CAAC,SAAS,SAAS;AACtB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,SAAS,IAAI,EAAG,SAAQ,MAAM,OAAO;AAAA,IAC7C;AAAA,IACA,MAAM,CAAC,SAAS,SAAS;AACrB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,SAAS,IAAI,EAAG,SAAQ,KAAK,OAAO;AAAA,IAC5C;AAAA,IACA,KAAK,CAAC,SAAS,SAAS;AACpB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,SAAS,IAAI,EAAG,SAAQ,IAAI,OAAO;AAAA,IAC3C;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
@@ -11,8 +11,8 @@ type RuntimeReporterMessage = {
11
11
  * The type for a full list of messages with their associated code and template
12
12
  * @since v0.1.0
13
13
  */
14
- type RuntimeReporterMessages<T extends RuntimeReporterMessage[]> = {
15
- [K in T[number]["code"]]: Extract<T[number], {
14
+ type RuntimeReporterMessages<T extends RuntimeReporterMessage> = {
15
+ [K in T["code"]]: Extract<T, {
16
16
  code: K;
17
17
  }>["template"];
18
18
  };
@@ -21,19 +21,24 @@ type RuntimeReporterMessages<T extends RuntimeReporterMessage[]> = {
21
21
  * @since v0.1.0
22
22
  */
23
23
  type RuntimeReporterToken = string | number | boolean | Error | null | undefined;
24
+ /**
25
+ * The type for a record of placeholder token names and their values
26
+ * @since v0.2.0
27
+ */
28
+ type RuntimeReporterTokens = Record<string, RuntimeReporterToken>;
24
29
  /**
25
30
  * A utility type used to determine the second argument of the runtime reporter methods
26
31
  * @private
27
32
  */
28
- type RuntimeReporterTokensArgs<T extends RuntimeReporterMessages<RuntimeReporterMessage[]>, U extends keyof T> = T extends RuntimeReporterMessages<infer V extends RuntimeReporterMessage[]> ? Extract<V[number], {
33
+ type RuntimeReporterTokensArgs<T extends RuntimeReporterMessages<RuntimeReporterMessage>, U extends keyof T> = T extends RuntimeReporterMessages<infer V extends RuntimeReporterMessage> ? Extract<V, {
29
34
  code: U;
30
35
  }>["tokens"] extends infer Tokens ? Tokens extends readonly string[] ? [tokens: Record<Tokens[number], RuntimeReporterToken>] : [] : [] : never;
31
36
  /**
32
37
  * The runtime report object with all of it's associated methods; the result
33
- * of the primary export: `createRuntimeReporter`
38
+ * of the primary export: `createReporter`
34
39
  * @private
35
40
  */
36
- interface RuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessage[]>> {
41
+ interface RuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessage>> {
37
42
  /**
38
43
  * Retrieves the full text of the targeted message
39
44
  *
@@ -47,8 +52,8 @@ interface RuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessa
47
52
  * Logs a warning to the console with the full text of the targeted message in non-production environments
48
53
  *
49
54
  * _Note: This method will only log when the message associated with the code is found;
50
- * meaning it will not be called in production if the `createRuntimeReporter` function
51
- * is provided an empty array._
55
+ * meaning it will not be called in production if the `createReporter` function
56
+ * is provided an empty message set._
52
57
  * @param code A direct reference to the unique code for the targeted message
53
58
  * @param args The remaining optional argument for the function; a record containing the placeholder token values
54
59
  */
@@ -57,8 +62,8 @@ interface RuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessa
57
62
  * Logs an error to the console with the full text of the targeted message in non-production environments
58
63
  *
59
64
  * _Note: This method will only log when the message associated with the code is found;
60
- * meaning it will not be called in production if the `createRuntimeReporter` function
61
- * is provided an empty array._
65
+ * meaning it will not be called in production if the `createReporter` function
66
+ * is provided an empty message set._
62
67
  * @param code A direct reference to the unique code for the targeted message
63
68
  * @param args The remaining optional argument for the function; a record containing the placeholder token values
64
69
  */
@@ -67,8 +72,8 @@ interface RuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessa
67
72
  * Logs a message to the console with the full text of the targeted message in non-production environments
68
73
  *
69
74
  * _Note: This method will only log when the message associated with the code is found;
70
- * meaning it will not be called in production if the `createRuntimeReporter` function
71
- * is provided an empty array._
75
+ * meaning it will not be called in production if the `createReporter` function
76
+ * is provided an empty message set._
72
77
  * @param code A direct reference to the unique code for the targeted message
73
78
  * @param args The remaining optional argument for the function; a record containing the placeholder token values
74
79
  */
@@ -76,8 +81,8 @@ interface RuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessa
76
81
  /**
77
82
  * Throws an error with the full text of the targeted message in all environments
78
83
  *
79
- * _Note: When the `createRuntimeReporter` function is called in production with an empty
80
- * array, this method will use the "defaultTemplate" option in this format: "<defaultTemplate> (<code>)"_
84
+ * _Note: When the `createReporter` function is called in production with an empty
85
+ * message set, this method will use the "defaultTemplate" option in this format: "<defaultTemplate> (<code>)"_
81
86
  * @param code A direct reference to the unique code for the targeted message
82
87
  * @param args The remaining optional argument for the function; a record containing the placeholder token values
83
88
  */
@@ -85,7 +90,7 @@ interface RuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessa
85
90
  }
86
91
  interface RuntimeReporterOptions {
87
92
  /**
88
- * A hook to format the message text univerally. By default, it
93
+ * A hook to format the message text universally. By default, it
89
94
  * outputs the message in the following format: "<message> (<code>)"
90
95
  * @param message The resolved message text; the placeholders have been replaced by their token values
91
96
  * @param code The unique code associated with the message
@@ -97,7 +102,7 @@ interface RuntimeReporterOptions {
97
102
  * have an associated message. Defaults to "An error occurred"
98
103
  *
99
104
  * _Note: This is only used when the `fail` method is called in production
100
- * environments when the `createRuntimeReporter` function is provided an empty array._
105
+ * environments when the `createReporter` function is provided an empty message set._
101
106
  */
102
107
  defaultTemplate?: string;
103
108
  }
@@ -107,6 +112,6 @@ interface RuntimeReporterOptions {
107
112
  * @param options Optional configuration options
108
113
  * @returns A runtime report object
109
114
  */
110
- declare function createRuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessage[]>>(messages: T, options?: RuntimeReporterOptions): RuntimeReporter<T>;
115
+ declare function createReporter<T extends RuntimeReporterMessages<RuntimeReporterMessage>>(messages: T, options?: RuntimeReporterOptions): RuntimeReporter<T>;
111
116
 
112
- export { type RuntimeReporterMessage, type RuntimeReporterMessages, type RuntimeReporterOptions, type RuntimeReporterToken, createRuntimeReporter };
117
+ export { type RuntimeReporterMessage, type RuntimeReporterMessages, type RuntimeReporterOptions, type RuntimeReporterToken, type RuntimeReporterTokens, createReporter };
package/dist/index.d.ts CHANGED
@@ -11,8 +11,8 @@ type RuntimeReporterMessage = {
11
11
  * The type for a full list of messages with their associated code and template
12
12
  * @since v0.1.0
13
13
  */
14
- type RuntimeReporterMessages<T extends RuntimeReporterMessage[]> = {
15
- [K in T[number]["code"]]: Extract<T[number], {
14
+ type RuntimeReporterMessages<T extends RuntimeReporterMessage> = {
15
+ [K in T["code"]]: Extract<T, {
16
16
  code: K;
17
17
  }>["template"];
18
18
  };
@@ -21,19 +21,24 @@ type RuntimeReporterMessages<T extends RuntimeReporterMessage[]> = {
21
21
  * @since v0.1.0
22
22
  */
23
23
  type RuntimeReporterToken = string | number | boolean | Error | null | undefined;
24
+ /**
25
+ * The type for a record of placeholder token names and their values
26
+ * @since v0.2.0
27
+ */
28
+ type RuntimeReporterTokens = Record<string, RuntimeReporterToken>;
24
29
  /**
25
30
  * A utility type used to determine the second argument of the runtime reporter methods
26
31
  * @private
27
32
  */
28
- type RuntimeReporterTokensArgs<T extends RuntimeReporterMessages<RuntimeReporterMessage[]>, U extends keyof T> = T extends RuntimeReporterMessages<infer V extends RuntimeReporterMessage[]> ? Extract<V[number], {
33
+ type RuntimeReporterTokensArgs<T extends RuntimeReporterMessages<RuntimeReporterMessage>, U extends keyof T> = T extends RuntimeReporterMessages<infer V extends RuntimeReporterMessage> ? Extract<V, {
29
34
  code: U;
30
35
  }>["tokens"] extends infer Tokens ? Tokens extends readonly string[] ? [tokens: Record<Tokens[number], RuntimeReporterToken>] : [] : [] : never;
31
36
  /**
32
37
  * The runtime report object with all of it's associated methods; the result
33
- * of the primary export: `createRuntimeReporter`
38
+ * of the primary export: `createReporter`
34
39
  * @private
35
40
  */
36
- interface RuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessage[]>> {
41
+ interface RuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessage>> {
37
42
  /**
38
43
  * Retrieves the full text of the targeted message
39
44
  *
@@ -47,8 +52,8 @@ interface RuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessa
47
52
  * Logs a warning to the console with the full text of the targeted message in non-production environments
48
53
  *
49
54
  * _Note: This method will only log when the message associated with the code is found;
50
- * meaning it will not be called in production if the `createRuntimeReporter` function
51
- * is provided an empty array._
55
+ * meaning it will not be called in production if the `createReporter` function
56
+ * is provided an empty message set._
52
57
  * @param code A direct reference to the unique code for the targeted message
53
58
  * @param args The remaining optional argument for the function; a record containing the placeholder token values
54
59
  */
@@ -57,8 +62,8 @@ interface RuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessa
57
62
  * Logs an error to the console with the full text of the targeted message in non-production environments
58
63
  *
59
64
  * _Note: This method will only log when the message associated with the code is found;
60
- * meaning it will not be called in production if the `createRuntimeReporter` function
61
- * is provided an empty array._
65
+ * meaning it will not be called in production if the `createReporter` function
66
+ * is provided an empty message set._
62
67
  * @param code A direct reference to the unique code for the targeted message
63
68
  * @param args The remaining optional argument for the function; a record containing the placeholder token values
64
69
  */
@@ -67,8 +72,8 @@ interface RuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessa
67
72
  * Logs a message to the console with the full text of the targeted message in non-production environments
68
73
  *
69
74
  * _Note: This method will only log when the message associated with the code is found;
70
- * meaning it will not be called in production if the `createRuntimeReporter` function
71
- * is provided an empty array._
75
+ * meaning it will not be called in production if the `createReporter` function
76
+ * is provided an empty message set._
72
77
  * @param code A direct reference to the unique code for the targeted message
73
78
  * @param args The remaining optional argument for the function; a record containing the placeholder token values
74
79
  */
@@ -76,8 +81,8 @@ interface RuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessa
76
81
  /**
77
82
  * Throws an error with the full text of the targeted message in all environments
78
83
  *
79
- * _Note: When the `createRuntimeReporter` function is called in production with an empty
80
- * array, this method will use the "defaultTemplate" option in this format: "<defaultTemplate> (<code>)"_
84
+ * _Note: When the `createReporter` function is called in production with an empty
85
+ * message set, this method will use the "defaultTemplate" option in this format: "<defaultTemplate> (<code>)"_
81
86
  * @param code A direct reference to the unique code for the targeted message
82
87
  * @param args The remaining optional argument for the function; a record containing the placeholder token values
83
88
  */
@@ -85,7 +90,7 @@ interface RuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessa
85
90
  }
86
91
  interface RuntimeReporterOptions {
87
92
  /**
88
- * A hook to format the message text univerally. By default, it
93
+ * A hook to format the message text universally. By default, it
89
94
  * outputs the message in the following format: "<message> (<code>)"
90
95
  * @param message The resolved message text; the placeholders have been replaced by their token values
91
96
  * @param code The unique code associated with the message
@@ -97,7 +102,7 @@ interface RuntimeReporterOptions {
97
102
  * have an associated message. Defaults to "An error occurred"
98
103
  *
99
104
  * _Note: This is only used when the `fail` method is called in production
100
- * environments when the `createRuntimeReporter` function is provided an empty array._
105
+ * environments when the `createReporter` function is provided an empty message set._
101
106
  */
102
107
  defaultTemplate?: string;
103
108
  }
@@ -107,6 +112,6 @@ interface RuntimeReporterOptions {
107
112
  * @param options Optional configuration options
108
113
  * @returns A runtime report object
109
114
  */
110
- declare function createRuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessage[]>>(messages: T, options?: RuntimeReporterOptions): RuntimeReporter<T>;
115
+ declare function createReporter<T extends RuntimeReporterMessages<RuntimeReporterMessage>>(messages: T, options?: RuntimeReporterOptions): RuntimeReporter<T>;
111
116
 
112
- export { type RuntimeReporterMessage, type RuntimeReporterMessages, type RuntimeReporterOptions, type RuntimeReporterToken, createRuntimeReporter };
117
+ export { type RuntimeReporterMessage, type RuntimeReporterMessages, type RuntimeReporterOptions, type RuntimeReporterToken, type RuntimeReporterTokens, createReporter };
package/dist/index.js CHANGED
@@ -1,17 +1,17 @@
1
- // index.ts
1
+ // src/index.ts
2
2
  var resolveTemplate = function resolveTemplate2(template, tokens) {
3
3
  let message = template;
4
4
  if (message) {
5
5
  Object.entries(tokens || {}).forEach((entry) => {
6
6
  const [token, value] = entry;
7
7
  const replace = value instanceof Error ? value.message : String(value ?? "");
8
- const santized = token.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
9
- message = message.replace(new RegExp(`\\{\\{\\s*${santized}\\s*\\}\\}`, "g"), replace);
8
+ const sanitized = token.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
9
+ message = message.replace(new RegExp(`\\{\\{\\s*${sanitized}\\s*\\}\\}`, "g"), replace);
10
10
  });
11
11
  }
12
12
  return message;
13
13
  };
14
- function createRuntimeReporter(messages, options = {}) {
14
+ function createReporter(messages, options = {}) {
15
15
  const {
16
16
  formatMessage = (message, code) => `${message} (${code})`,
17
17
  defaultTemplate = "An error occurred"
@@ -45,6 +45,6 @@ function createRuntimeReporter(messages, options = {}) {
45
45
  };
46
46
  }
47
47
  export {
48
- createRuntimeReporter
48
+ createReporter
49
49
  };
50
50
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../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[number][\"code\"]]: Extract<T[number], { 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 * A utility type used to determine the second argument of the runtime reporter methods\n * @private\n */\ntype RuntimeReporterTokensArgs<\n T extends RuntimeReporterMessages<RuntimeReporterMessage[]>,\n U extends keyof T,\n> =\n T extends RuntimeReporterMessages<infer V extends RuntimeReporterMessage[]>\n ? Extract<V[number], { code: U }>[\"tokens\"] extends infer Tokens\n ? Tokens extends readonly string[]\n ? [tokens: Record<Tokens[number], RuntimeReporterToken>]\n : []\n : []\n : never;\n\n/**\n * The runtime report object with all of it's associated methods; the result\n * of the primary export: `createRuntimeReporter`\n * @private\n */\ninterface RuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessage[]>> {\n /**\n * Retrieves the full text of the targeted message\n *\n * _Tip: This method is particularly useful in the test environment; allowing you\n * to make precise assertions without having to duplicate an 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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): string;\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 `createRuntimeReporter` function\n * is provided an empty array._\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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): 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 `createRuntimeReporter` function\n * is provided an empty array._\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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): 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 `createRuntimeReporter` function\n * is provided an empty array._\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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): void;\n\n /**\n * Throws an error with the full text of the targeted message in all environments\n *\n * _Note: When the `createRuntimeReporter` function is called in production with an empty\n * array, 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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): void;\n}\n\nexport interface RuntimeReporterOptions {\n /**\n * A hook to format the message text univerally. 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 `createRuntimeReporter` function is provided an empty array._\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 santized = token.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n message = message.replace(new RegExp(`\\\\{\\\\{\\\\s*${santized}\\\\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 createRuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessage[]>>(\n messages: T,\n options: RuntimeReporterOptions = {}\n): RuntimeReporter<T> {\n const {\n formatMessage = (message, code) => `${message} (${code})`,\n defaultTemplate = \"An error occurred\",\n } = options;\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 = messages[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 return getMessage(code, ...args);\n },\n error: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messages[code]) console.error(message);\n },\n warn: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messages[code]) console.warn(message);\n },\n log: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messages[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":";AA6IA,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,WAAW,MAAM,QAAQ,uBAAuB,MAAM;AAC5D,gBAAU,QAAQ,QAAQ,IAAI,OAAO,aAAa,QAAQ,cAAc,GAAG,GAAG,OAAO;AAAA,IACzF,CAAC;AAAA,EACL;AAEA,SAAO;AACX;AAQO,SAAS,sBACZ,UACA,UAAkC,CAAC,GACjB;AAClB,QAAM;AAAA,IACF,gBAAgB,CAAC,SAAS,SAAS,GAAG,OAAO,KAAK,IAAI;AAAA,IACtD,kBAAkB;AAAA,EACtB,IAAI;AAQJ,QAAM,aAAa,SAASC,YACxB,SACG,MACG;AACN,UAAM,WAAW,SAAS,IAAI,KAAK;AACnC,UAAM,SAAS,KAAK,CAAC;AACrB,UAAM,OAAO,gBAAgB,UAAU,MAAM;AAC7C,WAAO,cAAc,MAAM,IAAI;AAAA,EACnC;AAEA,SAAO;AAAA,IACH,SAAS,CAAC,SAAS,SAAS;AACxB,aAAO,WAAW,MAAM,GAAG,IAAI;AAAA,IACnC;AAAA,IACA,OAAO,CAAC,SAAS,SAAS;AACtB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,SAAS,IAAI,EAAG,SAAQ,MAAM,OAAO;AAAA,IAC7C;AAAA,IACA,MAAM,CAAC,SAAS,SAAS;AACrB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,SAAS,IAAI,EAAG,SAAQ,KAAK,OAAO;AAAA,IAC5C;AAAA,IACA,KAAK,CAAC,SAAS,SAAS;AACpB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,SAAS,IAAI,EAAG,SAAQ,IAAI,OAAO;AAAA,IAC3C;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 RuntimeReporterTokensArgs<\n T extends RuntimeReporterMessages<RuntimeReporterMessage>,\n U extends keyof T,\n> =\n T extends RuntimeReporterMessages<infer V extends RuntimeReporterMessage>\n ? Extract<V, { code: U }>[\"tokens\"] extends infer Tokens\n ? Tokens extends readonly string[]\n ? [tokens: Record<Tokens[number], RuntimeReporterToken>]\n : []\n : []\n : never;\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 RuntimeReporterMessages<RuntimeReporterMessage>> {\n /**\n * Retrieves the full text of the targeted message\n *\n * _Tip: This method is particularly useful in the test environment; allowing you\n * to make precise assertions without having to duplicate an 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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): string;\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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): 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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): 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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): 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 Extract<keyof T, string>>(\n code: U,\n ...args: RuntimeReporterTokensArgs<T, U>\n ): 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 RuntimeReporterMessages<RuntimeReporterMessage>>(\n messages: T,\n options: RuntimeReporterOptions = {}\n): RuntimeReporter<T> {\n const {\n formatMessage = (message, code) => `${message} (${code})`,\n defaultTemplate = \"An error occurred\",\n } = options;\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 = messages[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 return getMessage(code, ...args);\n },\n error: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messages[code]) console.error(message);\n },\n warn: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messages[code]) console.warn(message);\n },\n log: (code, ...args) => {\n const message = getMessage(code, ...args);\n if (messages[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":";AAmJA,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;AAQJ,QAAM,aAAa,SAASC,YACxB,SACG,MACG;AACN,UAAM,WAAW,SAAS,IAAI,KAAK;AACnC,UAAM,SAAS,KAAK,CAAC;AACrB,UAAM,OAAO,gBAAgB,UAAU,MAAM;AAC7C,WAAO,cAAc,MAAM,IAAI;AAAA,EACnC;AAEA,SAAO;AAAA,IACH,SAAS,CAAC,SAAS,SAAS;AACxB,aAAO,WAAW,MAAM,GAAG,IAAI;AAAA,IACnC;AAAA,IACA,OAAO,CAAC,SAAS,SAAS;AACtB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,SAAS,IAAI,EAAG,SAAQ,MAAM,OAAO;AAAA,IAC7C;AAAA,IACA,MAAM,CAAC,SAAS,SAAS;AACrB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,SAAS,IAAI,EAAG,SAAQ,KAAK,OAAO;AAAA,IAC5C;AAAA,IACA,KAAK,CAAC,SAAS,SAAS;AACpB,YAAM,UAAU,WAAW,MAAM,GAAG,IAAI;AACxC,UAAI,SAAS,IAAI,EAAG,SAAQ,IAAI,OAAO;AAAA,IAC3C;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.1.0",
4
- "description": "Runtime messaging that is convenient in development and secure in production",
3
+ "version": "0.3.0",
4
+ "description": "Structured runtime events for applications and frameworks. A composable foundation for logging, messaging, and runtime reporting.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
7
7
  "module": "./dist/index.js",
@@ -27,7 +27,7 @@
27
27
  }
28
28
  },
29
29
  "scripts": {
30
- "build": "tsup index.ts --format cjs,esm --dts --clean --sourcemap",
30
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean --sourcemap",
31
31
  "prepublishOnly": "npm run build",
32
32
  "test": "vitest run --coverage",
33
33
  "test:watch": "vitest",