lifecycleion 0.0.3 → 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 +1 -1
- package/dist/lib/curly-brackets.cjs +14 -3
- package/dist/lib/curly-brackets.cjs.map +1 -1
- package/dist/lib/curly-brackets.js +12 -3
- package/dist/lib/curly-brackets.js.map +1 -1
- package/dist/lib/lifecycle-manager/index.cjs +25 -0
- package/dist/lib/lifecycle-manager/index.cjs.map +1 -1
- package/dist/lib/lifecycle-manager/index.d.cts +5 -0
- package/dist/lib/lifecycle-manager/index.d.ts +5 -0
- package/dist/lib/lifecycle-manager/index.js +25 -0
- package/dist/lib/lifecycle-manager/index.js.map +1 -1
- package/dist/lib/logger/index.cjs +19 -7
- package/dist/lib/logger/index.cjs.map +1 -1
- package/dist/lib/logger/index.js +19 -7
- package/dist/lib/logger/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -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(
|
|
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
|
|
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":["
|
|
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(
|
|
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
|
|
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":["
|
|
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":[]}
|
|
@@ -1986,6 +1986,8 @@ var LifecycleManager = class extends EventEmitterProtected {
|
|
|
1986
1986
|
isShuttingDown = false;
|
|
1987
1987
|
// Unique token used to detect shutdowns that happened during async start().
|
|
1988
1988
|
shutdownToken = (0, import_ulid2.ulid)();
|
|
1989
|
+
// Resolver for the first logger.exit() deferred during an already-running shutdown.
|
|
1990
|
+
pendingLoggerExitResolve = null;
|
|
1989
1991
|
shutdownMethod = null;
|
|
1990
1992
|
lastShutdownResult = null;
|
|
1991
1993
|
// Signal management
|
|
@@ -3045,6 +3047,17 @@ var LifecycleManager = class extends EventEmitterProtected {
|
|
|
3045
3047
|
this.rootLogger.setBeforeExitCallback(
|
|
3046
3048
|
async (exitCode, isFirstExit) => {
|
|
3047
3049
|
if (this.isShuttingDown) {
|
|
3050
|
+
if (isFirstExit && this.pendingLoggerExitResolve === null) {
|
|
3051
|
+
this.logger.debug(
|
|
3052
|
+
"Logger exit called during shutdown, waiting...",
|
|
3053
|
+
{
|
|
3054
|
+
params: { exitCode }
|
|
3055
|
+
}
|
|
3056
|
+
);
|
|
3057
|
+
return await new Promise((resolve) => {
|
|
3058
|
+
this.pendingLoggerExitResolve = resolve;
|
|
3059
|
+
});
|
|
3060
|
+
}
|
|
3048
3061
|
this.logger.debug("Logger exit called during shutdown, waiting...", {
|
|
3049
3062
|
params: { exitCode }
|
|
3050
3063
|
});
|
|
@@ -4150,7 +4163,19 @@ var LifecycleManager = class extends EventEmitterProtected {
|
|
|
4150
4163
|
}
|
|
4151
4164
|
this.isShuttingDown = false;
|
|
4152
4165
|
this.updateStartedFlag();
|
|
4166
|
+
this.finalizePendingLoggerExit();
|
|
4167
|
+
}
|
|
4168
|
+
}
|
|
4169
|
+
/**
|
|
4170
|
+
* Release a deferred logger.exit() request after shutdown fully settles.
|
|
4171
|
+
*/
|
|
4172
|
+
finalizePendingLoggerExit() {
|
|
4173
|
+
if (this.pendingLoggerExitResolve === null || this.isShuttingDown) {
|
|
4174
|
+
return;
|
|
4153
4175
|
}
|
|
4176
|
+
const resolve = this.pendingLoggerExitResolve;
|
|
4177
|
+
this.pendingLoggerExitResolve = null;
|
|
4178
|
+
resolve({ action: "proceed" });
|
|
4154
4179
|
}
|
|
4155
4180
|
/**
|
|
4156
4181
|
* Retry shutdown for a stalled component.
|