runtime-reporter 0.1.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 ADDED
@@ -0,0 +1,44 @@
1
+ # Runtime Reporter
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
5
+
6
+ ### Usage
7
+
8
+ 1. Define your messages
9
+
10
+ ```ts
11
+ import { RuntimeReporterMessages } from "runtime-reporter";
12
+
13
+ type RuntimeMessages = Array<{
14
+ code: "ERR01";
15
+ template: "{{ componentName }} An error occured ...";
16
+ tokens: ["componentName"];
17
+ }>;
18
+
19
+ const messages: RuntimeReporterMessages<RuntimeMessages> = {
20
+ ERR01: "{{ componentName }} An error occured ...",
21
+ };
22
+ ```
23
+
24
+ 2. Create the reporter
25
+
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)`).
27
+
28
+ ```ts
29
+ import { createRuntimeReporter } = 'runtime-reporter';
30
+
31
+ const reporter = createRuntimeReporter(
32
+ process.env.NODE_ENV !== 'production' ? messages : ([] as RuntimeMessages)
33
+ );
34
+
35
+ export default reporter;
36
+ ```
37
+
38
+ 3. Call the reporter methods in your project
39
+
40
+ ```js
41
+ import reporter from "../my-runtime-reporter";
42
+
43
+ reporter.error("ERR01", { componentName: "MyComponent" });
44
+ ```
package/dist/index.cjs ADDED
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ createRuntimeReporter: () => createRuntimeReporter
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+ var resolveTemplate = function resolveTemplate2(template, tokens) {
27
+ let message = template;
28
+ if (message) {
29
+ Object.entries(tokens || {}).forEach((entry) => {
30
+ const [token, value] = entry;
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);
34
+ });
35
+ }
36
+ return message;
37
+ };
38
+ function createRuntimeReporter(messages, options = {}) {
39
+ const {
40
+ formatMessage = (message, code) => `${message} (${code})`,
41
+ defaultTemplate = "An error occurred"
42
+ } = options;
43
+ const getMessage = function getMessage2(code, ...args) {
44
+ const template = messages[code] || defaultTemplate;
45
+ const tokens = args[0];
46
+ const text = resolveTemplate(template, tokens);
47
+ return formatMessage(text, code);
48
+ };
49
+ return {
50
+ message: (code, ...args) => {
51
+ return getMessage(code, ...args);
52
+ },
53
+ error: (code, ...args) => {
54
+ const message = getMessage(code, ...args);
55
+ if (messages[code]) console.error(message);
56
+ },
57
+ warn: (code, ...args) => {
58
+ const message = getMessage(code, ...args);
59
+ if (messages[code]) console.warn(message);
60
+ },
61
+ log: (code, ...args) => {
62
+ const message = getMessage(code, ...args);
63
+ if (messages[code]) console.log(message);
64
+ },
65
+ fail: (code, ...args) => {
66
+ const message = getMessage(code, ...args);
67
+ throw new Error(message);
68
+ }
69
+ };
70
+ }
71
+ // Annotate the CommonJS export names for ESM import in node:
72
+ 0 && (module.exports = {
73
+ createRuntimeReporter
74
+ });
75
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +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"]}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * The type information for a single runtime reporter message
3
+ * @since v0.1.0
4
+ */
5
+ type RuntimeReporterMessage = {
6
+ code: string;
7
+ template: string;
8
+ tokens?: string[];
9
+ };
10
+ /**
11
+ * The type for a full list of messages with their associated code and template
12
+ * @since v0.1.0
13
+ */
14
+ type RuntimeReporterMessages<T extends RuntimeReporterMessage[]> = {
15
+ [K in T[number]["code"]]: Extract<T[number], {
16
+ code: K;
17
+ }>["template"];
18
+ };
19
+ /**
20
+ * The type for the supported values of a placeholder token
21
+ * @since v0.1.0
22
+ */
23
+ type RuntimeReporterToken = string | number | boolean | Error | null | undefined;
24
+ /**
25
+ * A utility type used to determine the second argument of the runtime reporter methods
26
+ * @private
27
+ */
28
+ type RuntimeReporterTokensArgs<T extends RuntimeReporterMessages<RuntimeReporterMessage[]>, U extends keyof T> = T extends RuntimeReporterMessages<infer V extends RuntimeReporterMessage[]> ? Extract<V[number], {
29
+ code: U;
30
+ }>["tokens"] extends infer Tokens ? Tokens extends readonly string[] ? [tokens: Record<Tokens[number], RuntimeReporterToken>] : [] : [] : never;
31
+ /**
32
+ * The runtime report object with all of it's associated methods; the result
33
+ * of the primary export: `createRuntimeReporter`
34
+ * @private
35
+ */
36
+ interface RuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessage[]>> {
37
+ /**
38
+ * Retrieves the full text of the targeted message
39
+ *
40
+ * _Tip: This method is particularly useful in the test environment; allowing you
41
+ * to make precise assertions without having to duplicate an of the raw message text._
42
+ * @param code A direct reference to the unique code for the targeted message
43
+ * @param args The remaining optional argument for the function; a record containing the placeholder token values
44
+ */
45
+ message<U extends Extract<keyof T, string>>(code: U, ...args: RuntimeReporterTokensArgs<T, U>): string;
46
+ /**
47
+ * Logs a warning to the console with the full text of the targeted message in non-production environments
48
+ *
49
+ * _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._
52
+ * @param code A direct reference to the unique code for the targeted message
53
+ * @param args The remaining optional argument for the function; a record containing the placeholder token values
54
+ */
55
+ warn<U extends Extract<keyof T, string>>(code: U, ...args: RuntimeReporterTokensArgs<T, U>): void;
56
+ /**
57
+ * Logs an error to the console with the full text of the targeted message in non-production environments
58
+ *
59
+ * _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._
62
+ * @param code A direct reference to the unique code for the targeted message
63
+ * @param args The remaining optional argument for the function; a record containing the placeholder token values
64
+ */
65
+ error<U extends Extract<keyof T, string>>(code: U, ...args: RuntimeReporterTokensArgs<T, U>): void;
66
+ /**
67
+ * Logs a message to the console with the full text of the targeted message in non-production environments
68
+ *
69
+ * _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._
72
+ * @param code A direct reference to the unique code for the targeted message
73
+ * @param args The remaining optional argument for the function; a record containing the placeholder token values
74
+ */
75
+ log<U extends Extract<keyof T, string>>(code: U, ...args: RuntimeReporterTokensArgs<T, U>): void;
76
+ /**
77
+ * Throws an error with the full text of the targeted message in all environments
78
+ *
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>)"_
81
+ * @param code A direct reference to the unique code for the targeted message
82
+ * @param args The remaining optional argument for the function; a record containing the placeholder token values
83
+ */
84
+ fail<U extends Extract<keyof T, string>>(code: U, ...args: RuntimeReporterTokensArgs<T, U>): void;
85
+ }
86
+ interface RuntimeReporterOptions {
87
+ /**
88
+ * A hook to format the message text univerally. By default, it
89
+ * outputs the message in the following format: "<message> (<code>)"
90
+ * @param message The resolved message text; the placeholders have been replaced by their token values
91
+ * @param code The unique code associated with the message
92
+ * @returns The final, fully formatted message
93
+ */
94
+ formatMessage?: (message: string, code: string) => string;
95
+ /**
96
+ * The default template to fallback on when a provided code does not
97
+ * have an associated message. Defaults to "An error occurred"
98
+ *
99
+ * _Note: This is only used when the `fail` method is called in production
100
+ * environments when the `createRuntimeReporter` function is provided an empty array._
101
+ */
102
+ defaultTemplate?: string;
103
+ }
104
+ /**
105
+ * Creates a reporter object with various helpful runtime methods
106
+ * @param messages The messages record organized by code and template
107
+ * @param options Optional configuration options
108
+ * @returns A runtime report object
109
+ */
110
+ declare function createRuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessage[]>>(messages: T, options?: RuntimeReporterOptions): RuntimeReporter<T>;
111
+
112
+ export { type RuntimeReporterMessage, type RuntimeReporterMessages, type RuntimeReporterOptions, type RuntimeReporterToken, createRuntimeReporter };
@@ -0,0 +1,112 @@
1
+ /**
2
+ * The type information for a single runtime reporter message
3
+ * @since v0.1.0
4
+ */
5
+ type RuntimeReporterMessage = {
6
+ code: string;
7
+ template: string;
8
+ tokens?: string[];
9
+ };
10
+ /**
11
+ * The type for a full list of messages with their associated code and template
12
+ * @since v0.1.0
13
+ */
14
+ type RuntimeReporterMessages<T extends RuntimeReporterMessage[]> = {
15
+ [K in T[number]["code"]]: Extract<T[number], {
16
+ code: K;
17
+ }>["template"];
18
+ };
19
+ /**
20
+ * The type for the supported values of a placeholder token
21
+ * @since v0.1.0
22
+ */
23
+ type RuntimeReporterToken = string | number | boolean | Error | null | undefined;
24
+ /**
25
+ * A utility type used to determine the second argument of the runtime reporter methods
26
+ * @private
27
+ */
28
+ type RuntimeReporterTokensArgs<T extends RuntimeReporterMessages<RuntimeReporterMessage[]>, U extends keyof T> = T extends RuntimeReporterMessages<infer V extends RuntimeReporterMessage[]> ? Extract<V[number], {
29
+ code: U;
30
+ }>["tokens"] extends infer Tokens ? Tokens extends readonly string[] ? [tokens: Record<Tokens[number], RuntimeReporterToken>] : [] : [] : never;
31
+ /**
32
+ * The runtime report object with all of it's associated methods; the result
33
+ * of the primary export: `createRuntimeReporter`
34
+ * @private
35
+ */
36
+ interface RuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessage[]>> {
37
+ /**
38
+ * Retrieves the full text of the targeted message
39
+ *
40
+ * _Tip: This method is particularly useful in the test environment; allowing you
41
+ * to make precise assertions without having to duplicate an of the raw message text._
42
+ * @param code A direct reference to the unique code for the targeted message
43
+ * @param args The remaining optional argument for the function; a record containing the placeholder token values
44
+ */
45
+ message<U extends Extract<keyof T, string>>(code: U, ...args: RuntimeReporterTokensArgs<T, U>): string;
46
+ /**
47
+ * Logs a warning to the console with the full text of the targeted message in non-production environments
48
+ *
49
+ * _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._
52
+ * @param code A direct reference to the unique code for the targeted message
53
+ * @param args The remaining optional argument for the function; a record containing the placeholder token values
54
+ */
55
+ warn<U extends Extract<keyof T, string>>(code: U, ...args: RuntimeReporterTokensArgs<T, U>): void;
56
+ /**
57
+ * Logs an error to the console with the full text of the targeted message in non-production environments
58
+ *
59
+ * _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._
62
+ * @param code A direct reference to the unique code for the targeted message
63
+ * @param args The remaining optional argument for the function; a record containing the placeholder token values
64
+ */
65
+ error<U extends Extract<keyof T, string>>(code: U, ...args: RuntimeReporterTokensArgs<T, U>): void;
66
+ /**
67
+ * Logs a message to the console with the full text of the targeted message in non-production environments
68
+ *
69
+ * _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._
72
+ * @param code A direct reference to the unique code for the targeted message
73
+ * @param args The remaining optional argument for the function; a record containing the placeholder token values
74
+ */
75
+ log<U extends Extract<keyof T, string>>(code: U, ...args: RuntimeReporterTokensArgs<T, U>): void;
76
+ /**
77
+ * Throws an error with the full text of the targeted message in all environments
78
+ *
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>)"_
81
+ * @param code A direct reference to the unique code for the targeted message
82
+ * @param args The remaining optional argument for the function; a record containing the placeholder token values
83
+ */
84
+ fail<U extends Extract<keyof T, string>>(code: U, ...args: RuntimeReporterTokensArgs<T, U>): void;
85
+ }
86
+ interface RuntimeReporterOptions {
87
+ /**
88
+ * A hook to format the message text univerally. By default, it
89
+ * outputs the message in the following format: "<message> (<code>)"
90
+ * @param message The resolved message text; the placeholders have been replaced by their token values
91
+ * @param code The unique code associated with the message
92
+ * @returns The final, fully formatted message
93
+ */
94
+ formatMessage?: (message: string, code: string) => string;
95
+ /**
96
+ * The default template to fallback on when a provided code does not
97
+ * have an associated message. Defaults to "An error occurred"
98
+ *
99
+ * _Note: This is only used when the `fail` method is called in production
100
+ * environments when the `createRuntimeReporter` function is provided an empty array._
101
+ */
102
+ defaultTemplate?: string;
103
+ }
104
+ /**
105
+ * Creates a reporter object with various helpful runtime methods
106
+ * @param messages The messages record organized by code and template
107
+ * @param options Optional configuration options
108
+ * @returns A runtime report object
109
+ */
110
+ declare function createRuntimeReporter<T extends RuntimeReporterMessages<RuntimeReporterMessage[]>>(messages: T, options?: RuntimeReporterOptions): RuntimeReporter<T>;
111
+
112
+ export { type RuntimeReporterMessage, type RuntimeReporterMessages, type RuntimeReporterOptions, type RuntimeReporterToken, createRuntimeReporter };
package/dist/index.js ADDED
@@ -0,0 +1,50 @@
1
+ // index.ts
2
+ var resolveTemplate = function resolveTemplate2(template, tokens) {
3
+ let message = template;
4
+ if (message) {
5
+ Object.entries(tokens || {}).forEach((entry) => {
6
+ const [token, value] = entry;
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);
10
+ });
11
+ }
12
+ return message;
13
+ };
14
+ function createRuntimeReporter(messages, options = {}) {
15
+ const {
16
+ formatMessage = (message, code) => `${message} (${code})`,
17
+ defaultTemplate = "An error occurred"
18
+ } = options;
19
+ const getMessage = function getMessage2(code, ...args) {
20
+ const template = messages[code] || defaultTemplate;
21
+ const tokens = args[0];
22
+ const text = resolveTemplate(template, tokens);
23
+ return formatMessage(text, code);
24
+ };
25
+ return {
26
+ message: (code, ...args) => {
27
+ return getMessage(code, ...args);
28
+ },
29
+ error: (code, ...args) => {
30
+ const message = getMessage(code, ...args);
31
+ if (messages[code]) console.error(message);
32
+ },
33
+ warn: (code, ...args) => {
34
+ const message = getMessage(code, ...args);
35
+ if (messages[code]) console.warn(message);
36
+ },
37
+ log: (code, ...args) => {
38
+ const message = getMessage(code, ...args);
39
+ if (messages[code]) console.log(message);
40
+ },
41
+ fail: (code, ...args) => {
42
+ const message = getMessage(code, ...args);
43
+ throw new Error(message);
44
+ }
45
+ };
46
+ }
47
+ export {
48
+ createRuntimeReporter
49
+ };
50
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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"]}
package/package.json ADDED
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "runtime-reporter",
3
+ "version": "0.1.0",
4
+ "description": "Runtime messaging that is convenient in development and secure in production",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "config": {
25
+ "commitizen": {
26
+ "path": "cz-conventional-changelog"
27
+ }
28
+ },
29
+ "scripts": {
30
+ "build": "tsup index.ts --format cjs,esm --dts --clean --sourcemap",
31
+ "prepublishOnly": "npm run build",
32
+ "test": "vitest run --coverage",
33
+ "test:watch": "vitest",
34
+ "lint": "eslint . --format eslint-formatter-compact",
35
+ "lint:fix": "eslint . --fix --format eslint-formatter-compact",
36
+ "format": "prettier --write .",
37
+ "format:check": "prettier --check .",
38
+ "commit": "cz",
39
+ "release": "release-it",
40
+ "prepare": "husky"
41
+ },
42
+ "lint-staged": {
43
+ "*.ts": [
44
+ "eslint --fix",
45
+ "prettier --write"
46
+ ]
47
+ },
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git+https://github.com/marksmccann/runtime-reporter.git"
51
+ },
52
+ "keywords": [
53
+ "runtime",
54
+ "reporter",
55
+ "messaging",
56
+ "console",
57
+ "error handling"
58
+ ],
59
+ "author": {
60
+ "name": "Mark McCann",
61
+ "email": "marksmccann@gmail.com"
62
+ },
63
+ "license": "MIT",
64
+ "bugs": {
65
+ "url": "https://github.com/marksmccann/runtime-reporter/issues"
66
+ },
67
+ "homepage": "https://github.com/marksmccann/runtime-reporter#readme",
68
+ "devDependencies": {
69
+ "@commitlint/cli": "^20.4.2",
70
+ "@commitlint/config-conventional": "^20.4.2",
71
+ "@eslint/js": "^10.0.1",
72
+ "@release-it/conventional-changelog": "^10.0.5",
73
+ "@typescript-eslint/eslint-plugin": "^8.56.0",
74
+ "@typescript-eslint/parser": "^8.56.0",
75
+ "@vitest/coverage-v8": "^4.0.18",
76
+ "commitizen": "^4.3.1",
77
+ "cz-conventional-changelog": "^3.3.0",
78
+ "eslint": "^10.0.1",
79
+ "eslint-config-prettier": "^10.1.8",
80
+ "eslint-formatter-compact": "^9.0.1",
81
+ "eslint-plugin-prettier": "^5.5.5",
82
+ "husky": "^9.1.7",
83
+ "lint-staged": "^16.2.7",
84
+ "prettier": "^3.8.1",
85
+ "release-it": "^19.2.4",
86
+ "tsup": "^8.5.1",
87
+ "typescript": "^5.9.3",
88
+ "typescript-eslint": "^8.56.0",
89
+ "vitest": "^4.0.18"
90
+ }
91
+ }