lifecycleion 0.0.4 → 0.0.5

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,4 +1,4 @@
1
- # Lifecycleion v0.0.4
1
+ # Lifecycleion v0.0.5
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/lifecycleion.svg)](https://badge.fury.io/js/lifecycleion)
4
4
 
@@ -23,6 +23,18 @@ __export(curly_brackets_exports, {
23
23
  CurlyBrackets: () => CurlyBrackets
24
24
  });
25
25
  module.exports = __toCommonJS(curly_brackets_exports);
26
+
27
+ // src/lib/internal/path-utils.ts
28
+ var PATH_SEGMENT_PATTERN = /\w+|\[(\d+)\]/g;
29
+ function getPathParts(path) {
30
+ return Array.from(
31
+ path.matchAll(PATH_SEGMENT_PATTERN),
32
+ (match) => match[1] ?? match[0]
33
+ );
34
+ }
35
+
36
+ // src/lib/curly-brackets.ts
37
+ var PLACEHOLDER_PATTERN = /(?:\\)?{{(\s*\w+(?:\[\d+\])*(?:\.\w+(?:\[\d+\])*)*\s*)(?:\\)?\s*}}/g;
26
38
  var CurlyBrackets = function(str = "", locals = {}, fallback = "(null)") {
27
39
  if (!str.includes("{{")) {
28
40
  return str;
@@ -31,9 +43,8 @@ var CurlyBrackets = function(str = "", locals = {}, fallback = "(null)") {
31
43
  return compiled(locals);
32
44
  };
33
45
  CurlyBrackets.compileTemplate = function(str, fallback = "(null)") {
34
- const pattern = /(?:\\)?{{(\s*[\w.]+?)(?:\\)?\s*}}/g;
35
46
  return (locals) => {
36
- return str.replace(pattern, (match, p1) => {
47
+ return str.replace(PLACEHOLDER_PATTERN, (match, p1) => {
37
48
  if (typeof p1 !== "string") {
38
49
  return match;
39
50
  }
@@ -50,7 +61,7 @@ CurlyBrackets.compileTemplate = function(str, fallback = "(null)") {
50
61
  return "{{" + p1.trim() + "}}";
51
62
  }
52
63
  const key = p1.trim();
53
- const parts = key.split(".");
64
+ const parts = getPathParts(key);
54
65
  let replacement = locals;
55
66
  for (const part of parts) {
56
67
  if (replacement !== void 0 && replacement !== null && typeof replacement === "object" && part in replacement) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/lib/curly-brackets.ts"],"sourcesContent":["export type TemplateFunction = (locals: Record<string, unknown>) => string;\n\ninterface CurlyBracketsFunction {\n (str?: string, locals?: Record<string, unknown>, fallback?: string): string;\n compileTemplate: (str: string, fallback?: string) => TemplateFunction;\n escape: (str: string) => string;\n}\n\n/**\n * Processes a template string, replacing placeholders with corresponding values from a provided object.\n *\n * @param {string} str - The template string to process.\n * @param locals - An object containing key-value pairs for placeholder replacement.\n * @param fallback - A default string to use when a placeholder's corresponding value is not found.\n * @returns - The processed string with placeholders replaced by their corresponding values.\n */\n\nconst CurlyBrackets: CurlyBracketsFunction = function (\n str: string = '',\n locals: Record<string, unknown> = {},\n fallback: string = '(null)',\n): string {\n // Short-circuit if no brackets - no need to process\n if (!str.includes('{{')) {\n return str;\n }\n\n const compiled = CurlyBrackets.compileTemplate(str, fallback);\n\n return compiled(locals);\n} as CurlyBracketsFunction;\n\n/**\n * Compiles a template string into a reusable function, which can be called with different sets of locals.\n * This is more efficient when you have a template that you want to use with different sets of locals,\n * as it avoids the overhead of parsing the template string each time it is used.\n *\n * @param {string} str - The template string to compile.\n * @param {string} fallback - A default string to use when a placeholder's corresponding value is not found in locals.\n * @returns A function that takes an object of locals and returns a processed string.\n */\n\nCurlyBrackets.compileTemplate = function (\n str: string,\n fallback: string = '(null)',\n): TemplateFunction {\n const pattern = /(?:\\\\)?{{(\\s*[\\w.]+?)(?:\\\\)?\\s*}}/g;\n\n return (locals: Record<string, unknown>): string => {\n return str.replace(pattern, (match, p1: string) => {\n if (typeof p1 !== 'string') {\n return match;\n }\n\n const hasLeadingEscape = match.startsWith('\\\\');\n const hasEndingEscape = match.endsWith('\\\\}}');\n const isFullyEscaped = hasLeadingEscape && hasEndingEscape;\n\n if (isFullyEscaped) {\n return match.slice(1, -3) + '}}';\n }\n\n if (hasLeadingEscape) {\n return match.slice(1);\n }\n\n if (hasEndingEscape) {\n return '{{' + p1.trim() + '}}';\n }\n\n const key = p1.trim();\n const parts = key.split('.');\n\n // Use a more specific approach to ensure the type is consistent\n let replacement: unknown = locals;\n\n for (const part of parts) {\n if (\n replacement !== undefined &&\n replacement !== null &&\n typeof replacement === 'object' &&\n part in replacement\n ) {\n replacement = (replacement as Record<string, unknown>)[part];\n } else {\n replacement = undefined;\n break;\n }\n }\n\n if (replacement === undefined || replacement === null) {\n return fallback;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n return String(replacement);\n });\n };\n};\n\n/**\n * Escapes placeholders in a string by prefixing them with a backslash, preventing them from being replaced when processed.\n *\n * @param {string} str - The string in which to escape placeholders.\n * @returns {string} - The string with placeholders escaped.\n */\n\nCurlyBrackets.escape = function (str: string): string {\n // Use a regex to replace instances of {{ and }} that are not already preceded by a backslash\n return str\n .replace(/(\\\\)?{{/g, (match, backslash) => (backslash ? match : '\\\\{{'))\n .replace(/(\\\\)?}}/g, (match, backslash) => (backslash ? match : '\\\\}}'));\n};\n\nexport { CurlyBrackets };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBA,IAAM,gBAAuC,SAC3C,MAAc,IACd,SAAkC,CAAC,GACnC,WAAmB,UACX;AAER,MAAI,CAAC,IAAI,SAAS,IAAI,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,cAAc,gBAAgB,KAAK,QAAQ;AAE5D,SAAO,SAAS,MAAM;AACxB;AAYA,cAAc,kBAAkB,SAC9B,KACA,WAAmB,UACD;AAClB,QAAM,UAAU;AAEhB,SAAO,CAAC,WAA4C;AAClD,WAAO,IAAI,QAAQ,SAAS,CAAC,OAAO,OAAe;AACjD,UAAI,OAAO,OAAO,UAAU;AAC1B,eAAO;AAAA,MACT;AAEA,YAAM,mBAAmB,MAAM,WAAW,IAAI;AAC9C,YAAM,kBAAkB,MAAM,SAAS,MAAM;AAC7C,YAAM,iBAAiB,oBAAoB;AAE3C,UAAI,gBAAgB;AAClB,eAAO,MAAM,MAAM,GAAG,EAAE,IAAI;AAAA,MAC9B;AAEA,UAAI,kBAAkB;AACpB,eAAO,MAAM,MAAM,CAAC;AAAA,MACtB;AAEA,UAAI,iBAAiB;AACnB,eAAO,OAAO,GAAG,KAAK,IAAI;AAAA,MAC5B;AAEA,YAAM,MAAM,GAAG,KAAK;AACpB,YAAM,QAAQ,IAAI,MAAM,GAAG;AAG3B,UAAI,cAAuB;AAE3B,iBAAW,QAAQ,OAAO;AACxB,YACE,gBAAgB,UAChB,gBAAgB,QAChB,OAAO,gBAAgB,YACvB,QAAQ,aACR;AACA,wBAAe,YAAwC,IAAI;AAAA,QAC7D,OAAO;AACL,wBAAc;AACd;AAAA,QACF;AAAA,MACF;AAEA,UAAI,gBAAgB,UAAa,gBAAgB,MAAM;AACrD,eAAO;AAAA,MACT;AAGA,aAAO,OAAO,WAAW;AAAA,IAC3B,CAAC;AAAA,EACH;AACF;AASA,cAAc,SAAS,SAAU,KAAqB;AAEpD,SAAO,IACJ,QAAQ,YAAY,CAAC,OAAO,cAAe,YAAY,QAAQ,MAAO,EACtE,QAAQ,YAAY,CAAC,OAAO,cAAe,YAAY,QAAQ,MAAO;AAC3E;","names":[]}
1
+ {"version":3,"sources":["../../src/lib/curly-brackets.ts","../../src/lib/internal/path-utils.ts"],"sourcesContent":["import { getPathParts } from './internal/path-utils';\n\nexport type TemplateFunction = (locals: Record<string, unknown>) => string;\n\ninterface CurlyBracketsFunction {\n (str?: string, locals?: Record<string, unknown>, fallback?: string): string;\n compileTemplate: (str: string, fallback?: string) => TemplateFunction;\n escape: (str: string) => string;\n}\n\nconst PLACEHOLDER_PATTERN =\n /(?:\\\\)?{{(\\s*\\w+(?:\\[\\d+\\])*(?:\\.\\w+(?:\\[\\d+\\])*)*\\s*)(?:\\\\)?\\s*}}/g;\n\n/**\n * Processes a template string, replacing placeholders with corresponding values from a provided object.\n *\n * @param {string} str - The template string to process.\n * @param locals - An object containing key-value pairs for placeholder replacement.\n * @param fallback - A default string to use when a placeholder's corresponding value is not found.\n * @returns - The processed string with placeholders replaced by their corresponding values.\n */\n\nconst CurlyBrackets: CurlyBracketsFunction = function (\n str: string = '',\n locals: Record<string, unknown> = {},\n fallback: string = '(null)',\n): string {\n // Short-circuit if no brackets - no need to process\n if (!str.includes('{{')) {\n return str;\n }\n\n const compiled = CurlyBrackets.compileTemplate(str, fallback);\n\n return compiled(locals);\n} as CurlyBracketsFunction;\n\n/**\n * Compiles a template string into a reusable function, which can be called with different sets of locals.\n * This is more efficient when you have a template that you want to use with different sets of locals,\n * as it avoids the overhead of parsing the template string each time it is used.\n *\n * @param {string} str - The template string to compile.\n * @param {string} fallback - A default string to use when a placeholder's corresponding value is not found in locals.\n * @returns A function that takes an object of locals and returns a processed string.\n */\n\nCurlyBrackets.compileTemplate = function (\n str: string,\n fallback: string = '(null)',\n): TemplateFunction {\n return (locals: Record<string, unknown>): string => {\n return str.replace(PLACEHOLDER_PATTERN, (match, p1: string) => {\n if (typeof p1 !== 'string') {\n return match;\n }\n\n const hasLeadingEscape = match.startsWith('\\\\');\n const hasEndingEscape = match.endsWith('\\\\}}');\n const isFullyEscaped = hasLeadingEscape && hasEndingEscape;\n\n if (isFullyEscaped) {\n return match.slice(1, -3) + '}}';\n }\n\n if (hasLeadingEscape) {\n return match.slice(1);\n }\n\n if (hasEndingEscape) {\n return '{{' + p1.trim() + '}}';\n }\n\n const key = p1.trim();\n const parts = getPathParts(key);\n\n // Use a more specific approach to ensure the type is consistent\n let replacement: unknown = locals;\n\n for (const part of parts) {\n if (\n replacement !== undefined &&\n replacement !== null &&\n typeof replacement === 'object' &&\n part in replacement\n ) {\n replacement = (replacement as Record<string, unknown>)[part];\n } else {\n replacement = undefined;\n break;\n }\n }\n\n if (replacement === undefined || replacement === null) {\n return fallback;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n return String(replacement);\n });\n };\n};\n\n/**\n * Escapes placeholders in a string by prefixing them with a backslash, preventing them from being replaced when processed.\n *\n * @param {string} str - The string in which to escape placeholders.\n * @returns {string} - The string with placeholders escaped.\n */\n\nCurlyBrackets.escape = function (str: string): string {\n // Use a regex to replace instances of {{ and }} that are not already preceded by a backslash\n return str\n .replace(/(\\\\)?{{/g, (match, backslash) => (backslash ? match : '\\\\{{'))\n .replace(/(\\\\)?}}/g, (match, backslash) => (backslash ? match : '\\\\}}'));\n};\n\nexport { CurlyBrackets };\n","const PATH_SEGMENT_PATTERN = /\\w+|\\[(\\d+)\\]/g;\n\n/**\n * Parses a mixed object/array path such as \"user.roles[0].name\" into lookup parts.\n */\nexport function getPathParts(path: string): string[] {\n return Array.from(\n path.matchAll(PATH_SEGMENT_PATTERN),\n (match) => match[1] ?? match[0],\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAM,uBAAuB;AAKtB,SAAS,aAAa,MAAwB;AACnD,SAAO,MAAM;AAAA,IACX,KAAK,SAAS,oBAAoB;AAAA,IAClC,CAAC,UAAU,MAAM,CAAC,KAAK,MAAM,CAAC;AAAA,EAChC;AACF;;;ADAA,IAAM,sBACJ;AAWF,IAAM,gBAAuC,SAC3C,MAAc,IACd,SAAkC,CAAC,GACnC,WAAmB,UACX;AAER,MAAI,CAAC,IAAI,SAAS,IAAI,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,cAAc,gBAAgB,KAAK,QAAQ;AAE5D,SAAO,SAAS,MAAM;AACxB;AAYA,cAAc,kBAAkB,SAC9B,KACA,WAAmB,UACD;AAClB,SAAO,CAAC,WAA4C;AAClD,WAAO,IAAI,QAAQ,qBAAqB,CAAC,OAAO,OAAe;AAC7D,UAAI,OAAO,OAAO,UAAU;AAC1B,eAAO;AAAA,MACT;AAEA,YAAM,mBAAmB,MAAM,WAAW,IAAI;AAC9C,YAAM,kBAAkB,MAAM,SAAS,MAAM;AAC7C,YAAM,iBAAiB,oBAAoB;AAE3C,UAAI,gBAAgB;AAClB,eAAO,MAAM,MAAM,GAAG,EAAE,IAAI;AAAA,MAC9B;AAEA,UAAI,kBAAkB;AACpB,eAAO,MAAM,MAAM,CAAC;AAAA,MACtB;AAEA,UAAI,iBAAiB;AACnB,eAAO,OAAO,GAAG,KAAK,IAAI;AAAA,MAC5B;AAEA,YAAM,MAAM,GAAG,KAAK;AACpB,YAAM,QAAQ,aAAa,GAAG;AAG9B,UAAI,cAAuB;AAE3B,iBAAW,QAAQ,OAAO;AACxB,YACE,gBAAgB,UAChB,gBAAgB,QAChB,OAAO,gBAAgB,YACvB,QAAQ,aACR;AACA,wBAAe,YAAwC,IAAI;AAAA,QAC7D,OAAO;AACL,wBAAc;AACd;AAAA,QACF;AAAA,MACF;AAEA,UAAI,gBAAgB,UAAa,gBAAgB,MAAM;AACrD,eAAO;AAAA,MACT;AAGA,aAAO,OAAO,WAAW;AAAA,IAC3B,CAAC;AAAA,EACH;AACF;AASA,cAAc,SAAS,SAAU,KAAqB;AAEpD,SAAO,IACJ,QAAQ,YAAY,CAAC,OAAO,cAAe,YAAY,QAAQ,MAAO,EACtE,QAAQ,YAAY,CAAC,OAAO,cAAe,YAAY,QAAQ,MAAO;AAC3E;","names":[]}
@@ -1,4 +1,14 @@
1
+ // src/lib/internal/path-utils.ts
2
+ var PATH_SEGMENT_PATTERN = /\w+|\[(\d+)\]/g;
3
+ function getPathParts(path) {
4
+ return Array.from(
5
+ path.matchAll(PATH_SEGMENT_PATTERN),
6
+ (match) => match[1] ?? match[0]
7
+ );
8
+ }
9
+
1
10
  // src/lib/curly-brackets.ts
11
+ var PLACEHOLDER_PATTERN = /(?:\\)?{{(\s*\w+(?:\[\d+\])*(?:\.\w+(?:\[\d+\])*)*\s*)(?:\\)?\s*}}/g;
2
12
  var CurlyBrackets = function(str = "", locals = {}, fallback = "(null)") {
3
13
  if (!str.includes("{{")) {
4
14
  return str;
@@ -7,9 +17,8 @@ var CurlyBrackets = function(str = "", locals = {}, fallback = "(null)") {
7
17
  return compiled(locals);
8
18
  };
9
19
  CurlyBrackets.compileTemplate = function(str, fallback = "(null)") {
10
- const pattern = /(?:\\)?{{(\s*[\w.]+?)(?:\\)?\s*}}/g;
11
20
  return (locals) => {
12
- return str.replace(pattern, (match, p1) => {
21
+ return str.replace(PLACEHOLDER_PATTERN, (match, p1) => {
13
22
  if (typeof p1 !== "string") {
14
23
  return match;
15
24
  }
@@ -26,7 +35,7 @@ CurlyBrackets.compileTemplate = function(str, fallback = "(null)") {
26
35
  return "{{" + p1.trim() + "}}";
27
36
  }
28
37
  const key = p1.trim();
29
- const parts = key.split(".");
38
+ const parts = getPathParts(key);
30
39
  let replacement = locals;
31
40
  for (const part of parts) {
32
41
  if (replacement !== void 0 && replacement !== null && typeof replacement === "object" && part in replacement) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/lib/curly-brackets.ts"],"sourcesContent":["export type TemplateFunction = (locals: Record<string, unknown>) => string;\n\ninterface CurlyBracketsFunction {\n (str?: string, locals?: Record<string, unknown>, fallback?: string): string;\n compileTemplate: (str: string, fallback?: string) => TemplateFunction;\n escape: (str: string) => string;\n}\n\n/**\n * Processes a template string, replacing placeholders with corresponding values from a provided object.\n *\n * @param {string} str - The template string to process.\n * @param locals - An object containing key-value pairs for placeholder replacement.\n * @param fallback - A default string to use when a placeholder's corresponding value is not found.\n * @returns - The processed string with placeholders replaced by their corresponding values.\n */\n\nconst CurlyBrackets: CurlyBracketsFunction = function (\n str: string = '',\n locals: Record<string, unknown> = {},\n fallback: string = '(null)',\n): string {\n // Short-circuit if no brackets - no need to process\n if (!str.includes('{{')) {\n return str;\n }\n\n const compiled = CurlyBrackets.compileTemplate(str, fallback);\n\n return compiled(locals);\n} as CurlyBracketsFunction;\n\n/**\n * Compiles a template string into a reusable function, which can be called with different sets of locals.\n * This is more efficient when you have a template that you want to use with different sets of locals,\n * as it avoids the overhead of parsing the template string each time it is used.\n *\n * @param {string} str - The template string to compile.\n * @param {string} fallback - A default string to use when a placeholder's corresponding value is not found in locals.\n * @returns A function that takes an object of locals and returns a processed string.\n */\n\nCurlyBrackets.compileTemplate = function (\n str: string,\n fallback: string = '(null)',\n): TemplateFunction {\n const pattern = /(?:\\\\)?{{(\\s*[\\w.]+?)(?:\\\\)?\\s*}}/g;\n\n return (locals: Record<string, unknown>): string => {\n return str.replace(pattern, (match, p1: string) => {\n if (typeof p1 !== 'string') {\n return match;\n }\n\n const hasLeadingEscape = match.startsWith('\\\\');\n const hasEndingEscape = match.endsWith('\\\\}}');\n const isFullyEscaped = hasLeadingEscape && hasEndingEscape;\n\n if (isFullyEscaped) {\n return match.slice(1, -3) + '}}';\n }\n\n if (hasLeadingEscape) {\n return match.slice(1);\n }\n\n if (hasEndingEscape) {\n return '{{' + p1.trim() + '}}';\n }\n\n const key = p1.trim();\n const parts = key.split('.');\n\n // Use a more specific approach to ensure the type is consistent\n let replacement: unknown = locals;\n\n for (const part of parts) {\n if (\n replacement !== undefined &&\n replacement !== null &&\n typeof replacement === 'object' &&\n part in replacement\n ) {\n replacement = (replacement as Record<string, unknown>)[part];\n } else {\n replacement = undefined;\n break;\n }\n }\n\n if (replacement === undefined || replacement === null) {\n return fallback;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n return String(replacement);\n });\n };\n};\n\n/**\n * Escapes placeholders in a string by prefixing them with a backslash, preventing them from being replaced when processed.\n *\n * @param {string} str - The string in which to escape placeholders.\n * @returns {string} - The string with placeholders escaped.\n */\n\nCurlyBrackets.escape = function (str: string): string {\n // Use a regex to replace instances of {{ and }} that are not already preceded by a backslash\n return str\n .replace(/(\\\\)?{{/g, (match, backslash) => (backslash ? match : '\\\\{{'))\n .replace(/(\\\\)?}}/g, (match, backslash) => (backslash ? match : '\\\\}}'));\n};\n\nexport { CurlyBrackets };\n"],"mappings":";AAiBA,IAAM,gBAAuC,SAC3C,MAAc,IACd,SAAkC,CAAC,GACnC,WAAmB,UACX;AAER,MAAI,CAAC,IAAI,SAAS,IAAI,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,cAAc,gBAAgB,KAAK,QAAQ;AAE5D,SAAO,SAAS,MAAM;AACxB;AAYA,cAAc,kBAAkB,SAC9B,KACA,WAAmB,UACD;AAClB,QAAM,UAAU;AAEhB,SAAO,CAAC,WAA4C;AAClD,WAAO,IAAI,QAAQ,SAAS,CAAC,OAAO,OAAe;AACjD,UAAI,OAAO,OAAO,UAAU;AAC1B,eAAO;AAAA,MACT;AAEA,YAAM,mBAAmB,MAAM,WAAW,IAAI;AAC9C,YAAM,kBAAkB,MAAM,SAAS,MAAM;AAC7C,YAAM,iBAAiB,oBAAoB;AAE3C,UAAI,gBAAgB;AAClB,eAAO,MAAM,MAAM,GAAG,EAAE,IAAI;AAAA,MAC9B;AAEA,UAAI,kBAAkB;AACpB,eAAO,MAAM,MAAM,CAAC;AAAA,MACtB;AAEA,UAAI,iBAAiB;AACnB,eAAO,OAAO,GAAG,KAAK,IAAI;AAAA,MAC5B;AAEA,YAAM,MAAM,GAAG,KAAK;AACpB,YAAM,QAAQ,IAAI,MAAM,GAAG;AAG3B,UAAI,cAAuB;AAE3B,iBAAW,QAAQ,OAAO;AACxB,YACE,gBAAgB,UAChB,gBAAgB,QAChB,OAAO,gBAAgB,YACvB,QAAQ,aACR;AACA,wBAAe,YAAwC,IAAI;AAAA,QAC7D,OAAO;AACL,wBAAc;AACd;AAAA,QACF;AAAA,MACF;AAEA,UAAI,gBAAgB,UAAa,gBAAgB,MAAM;AACrD,eAAO;AAAA,MACT;AAGA,aAAO,OAAO,WAAW;AAAA,IAC3B,CAAC;AAAA,EACH;AACF;AASA,cAAc,SAAS,SAAU,KAAqB;AAEpD,SAAO,IACJ,QAAQ,YAAY,CAAC,OAAO,cAAe,YAAY,QAAQ,MAAO,EACtE,QAAQ,YAAY,CAAC,OAAO,cAAe,YAAY,QAAQ,MAAO;AAC3E;","names":[]}
1
+ {"version":3,"sources":["../../src/lib/internal/path-utils.ts","../../src/lib/curly-brackets.ts"],"sourcesContent":["const PATH_SEGMENT_PATTERN = /\\w+|\\[(\\d+)\\]/g;\n\n/**\n * Parses a mixed object/array path such as \"user.roles[0].name\" into lookup parts.\n */\nexport function getPathParts(path: string): string[] {\n return Array.from(\n path.matchAll(PATH_SEGMENT_PATTERN),\n (match) => match[1] ?? match[0],\n );\n}\n","import { getPathParts } from './internal/path-utils';\n\nexport type TemplateFunction = (locals: Record<string, unknown>) => string;\n\ninterface CurlyBracketsFunction {\n (str?: string, locals?: Record<string, unknown>, fallback?: string): string;\n compileTemplate: (str: string, fallback?: string) => TemplateFunction;\n escape: (str: string) => string;\n}\n\nconst PLACEHOLDER_PATTERN =\n /(?:\\\\)?{{(\\s*\\w+(?:\\[\\d+\\])*(?:\\.\\w+(?:\\[\\d+\\])*)*\\s*)(?:\\\\)?\\s*}}/g;\n\n/**\n * Processes a template string, replacing placeholders with corresponding values from a provided object.\n *\n * @param {string} str - The template string to process.\n * @param locals - An object containing key-value pairs for placeholder replacement.\n * @param fallback - A default string to use when a placeholder's corresponding value is not found.\n * @returns - The processed string with placeholders replaced by their corresponding values.\n */\n\nconst CurlyBrackets: CurlyBracketsFunction = function (\n str: string = '',\n locals: Record<string, unknown> = {},\n fallback: string = '(null)',\n): string {\n // Short-circuit if no brackets - no need to process\n if (!str.includes('{{')) {\n return str;\n }\n\n const compiled = CurlyBrackets.compileTemplate(str, fallback);\n\n return compiled(locals);\n} as CurlyBracketsFunction;\n\n/**\n * Compiles a template string into a reusable function, which can be called with different sets of locals.\n * This is more efficient when you have a template that you want to use with different sets of locals,\n * as it avoids the overhead of parsing the template string each time it is used.\n *\n * @param {string} str - The template string to compile.\n * @param {string} fallback - A default string to use when a placeholder's corresponding value is not found in locals.\n * @returns A function that takes an object of locals and returns a processed string.\n */\n\nCurlyBrackets.compileTemplate = function (\n str: string,\n fallback: string = '(null)',\n): TemplateFunction {\n return (locals: Record<string, unknown>): string => {\n return str.replace(PLACEHOLDER_PATTERN, (match, p1: string) => {\n if (typeof p1 !== 'string') {\n return match;\n }\n\n const hasLeadingEscape = match.startsWith('\\\\');\n const hasEndingEscape = match.endsWith('\\\\}}');\n const isFullyEscaped = hasLeadingEscape && hasEndingEscape;\n\n if (isFullyEscaped) {\n return match.slice(1, -3) + '}}';\n }\n\n if (hasLeadingEscape) {\n return match.slice(1);\n }\n\n if (hasEndingEscape) {\n return '{{' + p1.trim() + '}}';\n }\n\n const key = p1.trim();\n const parts = getPathParts(key);\n\n // Use a more specific approach to ensure the type is consistent\n let replacement: unknown = locals;\n\n for (const part of parts) {\n if (\n replacement !== undefined &&\n replacement !== null &&\n typeof replacement === 'object' &&\n part in replacement\n ) {\n replacement = (replacement as Record<string, unknown>)[part];\n } else {\n replacement = undefined;\n break;\n }\n }\n\n if (replacement === undefined || replacement === null) {\n return fallback;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n return String(replacement);\n });\n };\n};\n\n/**\n * Escapes placeholders in a string by prefixing them with a backslash, preventing them from being replaced when processed.\n *\n * @param {string} str - The string in which to escape placeholders.\n * @returns {string} - The string with placeholders escaped.\n */\n\nCurlyBrackets.escape = function (str: string): string {\n // Use a regex to replace instances of {{ and }} that are not already preceded by a backslash\n return str\n .replace(/(\\\\)?{{/g, (match, backslash) => (backslash ? match : '\\\\{{'))\n .replace(/(\\\\)?}}/g, (match, backslash) => (backslash ? match : '\\\\}}'));\n};\n\nexport { CurlyBrackets };\n"],"mappings":";AAAA,IAAM,uBAAuB;AAKtB,SAAS,aAAa,MAAwB;AACnD,SAAO,MAAM;AAAA,IACX,KAAK,SAAS,oBAAoB;AAAA,IAClC,CAAC,UAAU,MAAM,CAAC,KAAK,MAAM,CAAC;AAAA,EAChC;AACF;;;ACAA,IAAM,sBACJ;AAWF,IAAM,gBAAuC,SAC3C,MAAc,IACd,SAAkC,CAAC,GACnC,WAAmB,UACX;AAER,MAAI,CAAC,IAAI,SAAS,IAAI,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,cAAc,gBAAgB,KAAK,QAAQ;AAE5D,SAAO,SAAS,MAAM;AACxB;AAYA,cAAc,kBAAkB,SAC9B,KACA,WAAmB,UACD;AAClB,SAAO,CAAC,WAA4C;AAClD,WAAO,IAAI,QAAQ,qBAAqB,CAAC,OAAO,OAAe;AAC7D,UAAI,OAAO,OAAO,UAAU;AAC1B,eAAO;AAAA,MACT;AAEA,YAAM,mBAAmB,MAAM,WAAW,IAAI;AAC9C,YAAM,kBAAkB,MAAM,SAAS,MAAM;AAC7C,YAAM,iBAAiB,oBAAoB;AAE3C,UAAI,gBAAgB;AAClB,eAAO,MAAM,MAAM,GAAG,EAAE,IAAI;AAAA,MAC9B;AAEA,UAAI,kBAAkB;AACpB,eAAO,MAAM,MAAM,CAAC;AAAA,MACtB;AAEA,UAAI,iBAAiB;AACnB,eAAO,OAAO,GAAG,KAAK,IAAI;AAAA,MAC5B;AAEA,YAAM,MAAM,GAAG,KAAK;AACpB,YAAM,QAAQ,aAAa,GAAG;AAG9B,UAAI,cAAuB;AAE3B,iBAAW,QAAQ,OAAO;AACxB,YACE,gBAAgB,UAChB,gBAAgB,QAChB,OAAO,gBAAgB,YACvB,QAAQ,aACR;AACA,wBAAe,YAAwC,IAAI;AAAA,QAC7D,OAAO;AACL,wBAAc;AACd;AAAA,QACF;AAAA,MACF;AAEA,UAAI,gBAAgB,UAAa,gBAAgB,MAAM;AACrD,eAAO;AAAA,MACT;AAGA,aAAO,OAAO,WAAW;AAAA,IAC3B,CAAC;AAAA,EACH;AACF;AASA,cAAc,SAAS,SAAU,KAAqB;AAEpD,SAAO,IACJ,QAAQ,YAAY,CAAC,OAAO,cAAe,YAAY,QAAQ,MAAO,EACtE,QAAQ,YAAY,CAAC,OAAO,cAAe,YAAY,QAAQ,MAAO;AAC3E;","names":[]}
@@ -934,7 +934,17 @@ function ms() {
934
934
  return Date.now();
935
935
  }
936
936
 
937
+ // src/lib/internal/path-utils.ts
938
+ var PATH_SEGMENT_PATTERN = /\w+|\[(\d+)\]/g;
939
+ function getPathParts(path) {
940
+ return Array.from(
941
+ path.matchAll(PATH_SEGMENT_PATTERN),
942
+ (match) => match[1] ?? match[0]
943
+ );
944
+ }
945
+
937
946
  // src/lib/curly-brackets.ts
947
+ var PLACEHOLDER_PATTERN = /(?:\\)?{{(\s*\w+(?:\[\d+\])*(?:\.\w+(?:\[\d+\])*)*\s*)(?:\\)?\s*}}/g;
938
948
  var CurlyBrackets = function(str = "", locals = {}, fallback = "(null)") {
939
949
  if (!str.includes("{{")) {
940
950
  return str;
@@ -943,9 +953,8 @@ var CurlyBrackets = function(str = "", locals = {}, fallback = "(null)") {
943
953
  return compiled(locals);
944
954
  };
945
955
  CurlyBrackets.compileTemplate = function(str, fallback = "(null)") {
946
- const pattern = /(?:\\)?{{(\s*[\w.]+?)(?:\\)?\s*}}/g;
947
956
  return (locals) => {
948
- return str.replace(pattern, (match, p1) => {
957
+ return str.replace(PLACEHOLDER_PATTERN, (match, p1) => {
949
958
  if (typeof p1 !== "string") {
950
959
  return match;
951
960
  }
@@ -962,7 +971,7 @@ CurlyBrackets.compileTemplate = function(str, fallback = "(null)") {
962
971
  return "{{" + p1.trim() + "}}";
963
972
  }
964
973
  const key = p1.trim();
965
- const parts = key.split(".");
974
+ const parts = getPathParts(key);
966
975
  let replacement = locals;
967
976
  for (const part of parts) {
968
977
  if (replacement !== void 0 && replacement !== null && typeof replacement === "object" && part in replacement) {
@@ -1308,10 +1317,13 @@ var defaultRedactFunction = (_keyName, value) => {
1308
1317
  return "***REDACTED***";
1309
1318
  };
1310
1319
  function setNestedValue(obj, path, value) {
1311
- const parts = path.split(".");
1320
+ const parts = getPathParts(path);
1312
1321
  let current = obj;
1313
1322
  for (let i = 0; i < parts.length - 1; i++) {
1314
1323
  const part = parts[i];
1324
+ if (current === void 0 || current === null || typeof current !== "object" || !(part in current)) {
1325
+ return;
1326
+ }
1315
1327
  const next = current[part];
1316
1328
  if (next === void 0 || next === null || typeof next !== "object") {
1317
1329
  return;
@@ -1319,12 +1331,12 @@ function setNestedValue(obj, path, value) {
1319
1331
  current = next;
1320
1332
  }
1321
1333
  const lastPart = parts[parts.length - 1];
1322
- if (lastPart !== void 0 && lastPart in current) {
1334
+ if (lastPart !== void 0 && current !== void 0 && current !== null && typeof current === "object" && lastPart in current) {
1323
1335
  current[lastPart] = value;
1324
1336
  }
1325
1337
  }
1326
1338
  function getNestedValue(obj, path) {
1327
- const parts = path.split(".");
1339
+ const parts = getPathParts(path);
1328
1340
  let current = obj;
1329
1341
  for (const part of parts) {
1330
1342
  if (current === void 0 || current === null || typeof current !== "object" || !(part in current)) {
@@ -1341,7 +1353,7 @@ function applyRedaction(params, redactedKeys, redactFunction) {
1341
1353
  const redactFn = redactFunction || defaultRedactFunction;
1342
1354
  const redactedParams = deepClone(params);
1343
1355
  for (const key of redactedKeys) {
1344
- if (key.includes(".")) {
1356
+ if (key.includes(".") || key.includes("[")) {
1345
1357
  const value = getNestedValue(redactedParams, key);
1346
1358
  if (value !== void 0) {
1347
1359
  const redactedValue = redactFn(key, value);