@emmett-community/emmett-expressjs-with-openapi 0.6.0 → 0.7.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/dist/{chunk-FSPH5TRT.cjs → chunk-HX5NHAJY.cjs} +14 -2
- package/dist/chunk-HX5NHAJY.cjs.map +1 -0
- package/dist/{chunk-PZBLPYJH.js → chunk-P6WGW2FK.js} +14 -2
- package/dist/{chunk-PZBLPYJH.js.map → chunk-P6WGW2FK.js.map} +1 -1
- package/dist/{handler-importer-YUZ7KENZ.cjs → handler-importer-F73SZ2KQ.cjs} +6 -6
- package/dist/{handler-importer-YUZ7KENZ.cjs.map → handler-importer-F73SZ2KQ.cjs.map} +1 -1
- package/dist/{handler-importer-3SFDETSW.js → handler-importer-SE6HRBDZ.js} +2 -2
- package/dist/index.cjs +12 -12
- package/dist/index.js +3 -3
- package/dist/{openapi-parser-SFYDJEIN.js → openapi-parser-CVIKTGAQ.js} +2 -2
- package/dist/{openapi-parser-HMWO3IPV.cjs → openapi-parser-G4KTMZEZ.cjs} +6 -6
- package/dist/{openapi-parser-HMWO3IPV.cjs.map → openapi-parser-G4KTMZEZ.cjs.map} +1 -1
- package/package.json +1 -1
- package/dist/chunk-FSPH5TRT.cjs.map +0 -1
- /package/dist/{handler-importer-3SFDETSW.js.map → handler-importer-SE6HRBDZ.js.map} +0 -0
- /package/dist/{openapi-parser-SFYDJEIN.js.map → openapi-parser-CVIKTGAQ.js.map} +0 -0
|
@@ -10,7 +10,7 @@ var safeLog = {
|
|
|
10
10
|
},
|
|
11
11
|
warn: (logger, msg, data) => {
|
|
12
12
|
if (!logger) return;
|
|
13
|
-
logger.warn(
|
|
13
|
+
logger.warn(normalizeWarnContext(data), msg);
|
|
14
14
|
},
|
|
15
15
|
error: (logger, msg, error) => {
|
|
16
16
|
if (!logger) return;
|
|
@@ -26,6 +26,18 @@ function normalizeContext(data) {
|
|
|
26
26
|
}
|
|
27
27
|
return { data };
|
|
28
28
|
}
|
|
29
|
+
function normalizeWarnContext(data) {
|
|
30
|
+
if (data === void 0 || data === null) {
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
if (data instanceof Error) {
|
|
34
|
+
return { err: data };
|
|
35
|
+
}
|
|
36
|
+
if (typeof data === "object" && !Array.isArray(data)) {
|
|
37
|
+
return { ...data };
|
|
38
|
+
}
|
|
39
|
+
return { data };
|
|
40
|
+
}
|
|
29
41
|
function normalizeErrorContext(error) {
|
|
30
42
|
if (error === void 0 || error === null) {
|
|
31
43
|
return {};
|
|
@@ -42,4 +54,4 @@ function normalizeErrorContext(error) {
|
|
|
42
54
|
|
|
43
55
|
|
|
44
56
|
exports.safeLog = safeLog;
|
|
45
|
-
//# sourceMappingURL=chunk-
|
|
57
|
+
//# sourceMappingURL=chunk-HX5NHAJY.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/emmett-expressjs-with-openapi/emmett-expressjs-with-openapi/dist/chunk-HX5NHAJY.cjs","../src/observability.ts"],"names":[],"mappings":"AAAA;AC+FO,IAAM,QAAA,EAAU;AAAA,EACrB,KAAA,EAAO,CAAC,MAAA,EAA4B,GAAA,EAAa,IAAA,EAAA,GAAmB;AAClE,IAAA,GAAA,CAAI,CAAC,MAAA,EAAQ,MAAA;AACb,IAAA,MAAA,CAAO,KAAA,CAAM,gBAAA,CAAiB,IAAI,CAAA,EAAG,GAAG,CAAA;AAAA,EAC1C,CAAA;AAAA,EACA,IAAA,EAAM,CAAC,MAAA,EAA4B,GAAA,EAAa,IAAA,EAAA,GAAmB;AACjE,IAAA,GAAA,CAAI,CAAC,MAAA,EAAQ,MAAA;AACb,IAAA,MAAA,CAAO,IAAA,CAAK,gBAAA,CAAiB,IAAI,CAAA,EAAG,GAAG,CAAA;AAAA,EACzC,CAAA;AAAA,EACA,IAAA,EAAM,CAAC,MAAA,EAA4B,GAAA,EAAa,IAAA,EAAA,GAAmB;AACjE,IAAA,GAAA,CAAI,CAAC,MAAA,EAAQ,MAAA;AACb,IAAA,MAAA,CAAO,IAAA,CAAK,oBAAA,CAAqB,IAAI,CAAA,EAAG,GAAG,CAAA;AAAA,EAC7C,CAAA;AAAA,EACA,KAAA,EAAO,CAAC,MAAA,EAA4B,GAAA,EAAa,KAAA,EAAA,GAAoB;AACnE,IAAA,GAAA,CAAI,CAAC,MAAA,EAAQ,MAAA;AACb,IAAA,MAAA,CAAO,KAAA,CAAM,qBAAA,CAAsB,KAAK,CAAA,EAAG,GAAG,CAAA;AAAA,EAChD;AACF,CAAA;AAMA,SAAS,gBAAA,CAAiB,IAAA,EAAwC;AAChE,EAAA,GAAA,CAAI,KAAA,IAAS,KAAA,EAAA,GAAa,KAAA,IAAS,IAAA,EAAM;AACvC,IAAA,OAAO,CAAC,CAAA;AAAA,EACV;AACA,EAAA,GAAA,CAAI,OAAO,KAAA,IAAS,SAAA,GAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,EAAG;AACpD,IAAA,OAAO,EAAE,GAAI,KAAiC,CAAA;AAAA,EAChD;AACA,EAAA,OAAO,EAAE,KAAK,CAAA;AAChB;AAOA,SAAS,oBAAA,CAAqB,IAAA,EAAwC;AACpE,EAAA,GAAA,CAAI,KAAA,IAAS,KAAA,EAAA,GAAa,KAAA,IAAS,IAAA,EAAM;AACvC,IAAA,OAAO,CAAC,CAAA;AAAA,EACV;AACA,EAAA,GAAA,CAAI,KAAA,WAAgB,KAAA,EAAO;AACzB,IAAA,OAAO,EAAE,GAAA,EAAK,KAAK,CAAA;AAAA,EACrB;AACA,EAAA,GAAA,CAAI,OAAO,KAAA,IAAS,SAAA,GAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,EAAG;AACpD,IAAA,OAAO,EAAE,GAAI,KAAiC,CAAA;AAAA,EAChD;AACA,EAAA,OAAO,EAAE,KAAK,CAAA;AAChB;AAOA,SAAS,qBAAA,CAAsB,KAAA,EAAyC;AACtE,EAAA,GAAA,CAAI,MAAA,IAAU,KAAA,EAAA,GAAa,MAAA,IAAU,IAAA,EAAM;AACzC,IAAA,OAAO,CAAC,CAAA;AAAA,EACV;AACA,EAAA,GAAA,CAAI,MAAA,WAAiB,KAAA,EAAO;AAC1B,IAAA,OAAO,EAAE,GAAA,EAAK,MAAM,CAAA;AAAA,EACtB;AACA,EAAA,GAAA,CAAI,OAAO,MAAA,IAAU,SAAA,GAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACtD,IAAA,OAAO,EAAE,GAAI,MAAkC,CAAA;AAAA,EACjD;AACA,EAAA,OAAO,EAAE,GAAA,EAAK,MAAM,CAAA;AACtB;AD9GA;AACA;AACE;AACF,0BAAC","file":"/home/runner/work/emmett-expressjs-with-openapi/emmett-expressjs-with-openapi/dist/chunk-HX5NHAJY.cjs","sourcesContent":[null,"/**\n * Observability types for emmett-expressjs-with-openapi.\n *\n * This module provides optional logging integration\n * following a \"silent by default\" philosophy.\n */\n\n/**\n * Canonical Logger contract for the Emmett ecosystem.\n *\n * This package defines the canonical Logger interface.\n * Implementations (Pino, Winston, etc.) MUST adapt to this contract.\n * This contract MUST NOT adapt to any specific implementation.\n *\n * Semantic Rules:\n * - context (first parameter): ALWAYS structured data as Record<string, unknown>\n * - message (second parameter): ALWAYS the human-readable log message\n * - The order is NEVER inverted\n * - The (message, data) form is NOT valid for this contract\n *\n * @example\n * ```typescript\n * // Pino - native compatibility\n * import pino from 'pino';\n * const logger = pino();\n * // logger.info({ orderId }, 'Order created') matches our contract\n * ```\n */\nexport interface Logger {\n /**\n * Log debug-level message with structured context.\n * @param context - Structured data to include in the log entry\n * @param message - Optional human-readable message\n */\n debug(context: Record<string, unknown>, message?: string): void;\n\n /**\n * Log info-level message with structured context.\n * @param context - Structured data to include in the log entry\n * @param message - Optional human-readable message\n */\n info(context: Record<string, unknown>, message?: string): void;\n\n /**\n * Log warn-level message with structured context.\n * @param context - Structured data to include in the log entry\n * @param message - Optional human-readable message\n */\n warn(context: Record<string, unknown>, message?: string): void;\n\n /**\n * Log error-level message with structured context.\n * @param context - Structured data to include in the log entry (may include 'err' key)\n * @param message - Optional human-readable message\n */\n error(context: Record<string, unknown>, message?: string): void;\n}\n\n/**\n * Observability configuration options.\n */\nexport type ObservabilityOptions = {\n /**\n * Optional logger instance for diagnostic output.\n * When not provided, the library operates silently.\n *\n * @example\n * ```typescript\n * import pino from 'pino';\n *\n * const logger = pino();\n *\n * const app = await getApplication({\n * observability: { logger },\n * });\n * ```\n */\n logger?: Logger;\n};\n\n/**\n * Internal helper to safely call logger methods.\n *\n * IMPORTANT: safeLog is the ONLY translation point between internal usage\n * and the Logger contract.\n *\n * Internal Usage Pattern:\n * safeLog.info(logger, 'Order created', { orderId: 123 })\n *\n * Translation to Logger Contract:\n * logger.info({ orderId: 123 }, 'Order created')\n *\n * This allows ergonomic internal usage while ensuring all injected loggers\n * receive calls in the canonical (context, message) format.\n */\nexport const safeLog = {\n debug: (logger: Logger | undefined, msg: string, data?: unknown) => {\n if (!logger) return;\n logger.debug(normalizeContext(data), msg);\n },\n info: (logger: Logger | undefined, msg: string, data?: unknown) => {\n if (!logger) return;\n logger.info(normalizeContext(data), msg);\n },\n warn: (logger: Logger | undefined, msg: string, data?: unknown) => {\n if (!logger) return;\n logger.warn(normalizeWarnContext(data), msg);\n },\n error: (logger: Logger | undefined, msg: string, error?: unknown) => {\n if (!logger) return;\n logger.error(normalizeErrorContext(error), msg);\n },\n};\n\n/**\n * Normalize data to context object for regular log methods.\n * Creates a shallow copy to avoid accidental mutation of the original object.\n */\nfunction normalizeContext(data: unknown): Record<string, unknown> {\n if (data === undefined || data === null) {\n return {};\n }\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n}\n\n/**\n * Normalize data to context object for warn log method.\n * Uses 'err' key for Error instances to prevent property leakage (like 'name' overwriting logger name).\n * Creates a shallow copy to avoid accidental mutation of the original object.\n */\nfunction normalizeWarnContext(data: unknown): Record<string, unknown> {\n if (data === undefined || data === null) {\n return {};\n }\n if (data instanceof Error) {\n return { err: data };\n }\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n}\n\n/**\n * Normalize error to context object for error log method.\n * Uses 'err' key for Pino compatibility (Pino serializes Error objects on 'err' key).\n * Creates a shallow copy to avoid accidental mutation of the original object.\n */\nfunction normalizeErrorContext(error: unknown): Record<string, unknown> {\n if (error === undefined || error === null) {\n return {};\n }\n if (error instanceof Error) {\n return { err: error };\n }\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n}\n"]}
|
|
@@ -10,7 +10,7 @@ var safeLog = {
|
|
|
10
10
|
},
|
|
11
11
|
warn: (logger, msg, data) => {
|
|
12
12
|
if (!logger) return;
|
|
13
|
-
logger.warn(
|
|
13
|
+
logger.warn(normalizeWarnContext(data), msg);
|
|
14
14
|
},
|
|
15
15
|
error: (logger, msg, error) => {
|
|
16
16
|
if (!logger) return;
|
|
@@ -26,6 +26,18 @@ function normalizeContext(data) {
|
|
|
26
26
|
}
|
|
27
27
|
return { data };
|
|
28
28
|
}
|
|
29
|
+
function normalizeWarnContext(data) {
|
|
30
|
+
if (data === void 0 || data === null) {
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
if (data instanceof Error) {
|
|
34
|
+
return { err: data };
|
|
35
|
+
}
|
|
36
|
+
if (typeof data === "object" && !Array.isArray(data)) {
|
|
37
|
+
return { ...data };
|
|
38
|
+
}
|
|
39
|
+
return { data };
|
|
40
|
+
}
|
|
29
41
|
function normalizeErrorContext(error) {
|
|
30
42
|
if (error === void 0 || error === null) {
|
|
31
43
|
return {};
|
|
@@ -42,4 +54,4 @@ function normalizeErrorContext(error) {
|
|
|
42
54
|
export {
|
|
43
55
|
safeLog
|
|
44
56
|
};
|
|
45
|
-
//# sourceMappingURL=chunk-
|
|
57
|
+
//# sourceMappingURL=chunk-P6WGW2FK.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/observability.ts"],"sourcesContent":["/**\n * Observability types for emmett-expressjs-with-openapi.\n *\n * This module provides optional logging integration\n * following a \"silent by default\" philosophy.\n */\n\n/**\n * Canonical Logger contract for the Emmett ecosystem.\n *\n * This package defines the canonical Logger interface.\n * Implementations (Pino, Winston, etc.) MUST adapt to this contract.\n * This contract MUST NOT adapt to any specific implementation.\n *\n * Semantic Rules:\n * - context (first parameter): ALWAYS structured data as Record<string, unknown>\n * - message (second parameter): ALWAYS the human-readable log message\n * - The order is NEVER inverted\n * - The (message, data) form is NOT valid for this contract\n *\n * @example\n * ```typescript\n * // Pino - native compatibility\n * import pino from 'pino';\n * const logger = pino();\n * // logger.info({ orderId }, 'Order created') matches our contract\n * ```\n */\nexport interface Logger {\n /**\n * Log debug-level message with structured context.\n * @param context - Structured data to include in the log entry\n * @param message - Optional human-readable message\n */\n debug(context: Record<string, unknown>, message?: string): void;\n\n /**\n * Log info-level message with structured context.\n * @param context - Structured data to include in the log entry\n * @param message - Optional human-readable message\n */\n info(context: Record<string, unknown>, message?: string): void;\n\n /**\n * Log warn-level message with structured context.\n * @param context - Structured data to include in the log entry\n * @param message - Optional human-readable message\n */\n warn(context: Record<string, unknown>, message?: string): void;\n\n /**\n * Log error-level message with structured context.\n * @param context - Structured data to include in the log entry (may include 'err' key)\n * @param message - Optional human-readable message\n */\n error(context: Record<string, unknown>, message?: string): void;\n}\n\n/**\n * Observability configuration options.\n */\nexport type ObservabilityOptions = {\n /**\n * Optional logger instance for diagnostic output.\n * When not provided, the library operates silently.\n *\n * @example\n * ```typescript\n * import pino from 'pino';\n *\n * const logger = pino();\n *\n * const app = await getApplication({\n * observability: { logger },\n * });\n * ```\n */\n logger?: Logger;\n};\n\n/**\n * Internal helper to safely call logger methods.\n *\n * IMPORTANT: safeLog is the ONLY translation point between internal usage\n * and the Logger contract.\n *\n * Internal Usage Pattern:\n * safeLog.info(logger, 'Order created', { orderId: 123 })\n *\n * Translation to Logger Contract:\n * logger.info({ orderId: 123 }, 'Order created')\n *\n * This allows ergonomic internal usage while ensuring all injected loggers\n * receive calls in the canonical (context, message) format.\n */\nexport const safeLog = {\n debug: (logger: Logger | undefined, msg: string, data?: unknown) => {\n if (!logger) return;\n logger.debug(normalizeContext(data), msg);\n },\n info: (logger: Logger | undefined, msg: string, data?: unknown) => {\n if (!logger) return;\n logger.info(normalizeContext(data), msg);\n },\n warn: (logger: Logger | undefined, msg: string, data?: unknown) => {\n if (!logger) return;\n logger.warn(
|
|
1
|
+
{"version":3,"sources":["../src/observability.ts"],"sourcesContent":["/**\n * Observability types for emmett-expressjs-with-openapi.\n *\n * This module provides optional logging integration\n * following a \"silent by default\" philosophy.\n */\n\n/**\n * Canonical Logger contract for the Emmett ecosystem.\n *\n * This package defines the canonical Logger interface.\n * Implementations (Pino, Winston, etc.) MUST adapt to this contract.\n * This contract MUST NOT adapt to any specific implementation.\n *\n * Semantic Rules:\n * - context (first parameter): ALWAYS structured data as Record<string, unknown>\n * - message (second parameter): ALWAYS the human-readable log message\n * - The order is NEVER inverted\n * - The (message, data) form is NOT valid for this contract\n *\n * @example\n * ```typescript\n * // Pino - native compatibility\n * import pino from 'pino';\n * const logger = pino();\n * // logger.info({ orderId }, 'Order created') matches our contract\n * ```\n */\nexport interface Logger {\n /**\n * Log debug-level message with structured context.\n * @param context - Structured data to include in the log entry\n * @param message - Optional human-readable message\n */\n debug(context: Record<string, unknown>, message?: string): void;\n\n /**\n * Log info-level message with structured context.\n * @param context - Structured data to include in the log entry\n * @param message - Optional human-readable message\n */\n info(context: Record<string, unknown>, message?: string): void;\n\n /**\n * Log warn-level message with structured context.\n * @param context - Structured data to include in the log entry\n * @param message - Optional human-readable message\n */\n warn(context: Record<string, unknown>, message?: string): void;\n\n /**\n * Log error-level message with structured context.\n * @param context - Structured data to include in the log entry (may include 'err' key)\n * @param message - Optional human-readable message\n */\n error(context: Record<string, unknown>, message?: string): void;\n}\n\n/**\n * Observability configuration options.\n */\nexport type ObservabilityOptions = {\n /**\n * Optional logger instance for diagnostic output.\n * When not provided, the library operates silently.\n *\n * @example\n * ```typescript\n * import pino from 'pino';\n *\n * const logger = pino();\n *\n * const app = await getApplication({\n * observability: { logger },\n * });\n * ```\n */\n logger?: Logger;\n};\n\n/**\n * Internal helper to safely call logger methods.\n *\n * IMPORTANT: safeLog is the ONLY translation point between internal usage\n * and the Logger contract.\n *\n * Internal Usage Pattern:\n * safeLog.info(logger, 'Order created', { orderId: 123 })\n *\n * Translation to Logger Contract:\n * logger.info({ orderId: 123 }, 'Order created')\n *\n * This allows ergonomic internal usage while ensuring all injected loggers\n * receive calls in the canonical (context, message) format.\n */\nexport const safeLog = {\n debug: (logger: Logger | undefined, msg: string, data?: unknown) => {\n if (!logger) return;\n logger.debug(normalizeContext(data), msg);\n },\n info: (logger: Logger | undefined, msg: string, data?: unknown) => {\n if (!logger) return;\n logger.info(normalizeContext(data), msg);\n },\n warn: (logger: Logger | undefined, msg: string, data?: unknown) => {\n if (!logger) return;\n logger.warn(normalizeWarnContext(data), msg);\n },\n error: (logger: Logger | undefined, msg: string, error?: unknown) => {\n if (!logger) return;\n logger.error(normalizeErrorContext(error), msg);\n },\n};\n\n/**\n * Normalize data to context object for regular log methods.\n * Creates a shallow copy to avoid accidental mutation of the original object.\n */\nfunction normalizeContext(data: unknown): Record<string, unknown> {\n if (data === undefined || data === null) {\n return {};\n }\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n}\n\n/**\n * Normalize data to context object for warn log method.\n * Uses 'err' key for Error instances to prevent property leakage (like 'name' overwriting logger name).\n * Creates a shallow copy to avoid accidental mutation of the original object.\n */\nfunction normalizeWarnContext(data: unknown): Record<string, unknown> {\n if (data === undefined || data === null) {\n return {};\n }\n if (data instanceof Error) {\n return { err: data };\n }\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n}\n\n/**\n * Normalize error to context object for error log method.\n * Uses 'err' key for Pino compatibility (Pino serializes Error objects on 'err' key).\n * Creates a shallow copy to avoid accidental mutation of the original object.\n */\nfunction normalizeErrorContext(error: unknown): Record<string, unknown> {\n if (error === undefined || error === null) {\n return {};\n }\n if (error instanceof Error) {\n return { err: error };\n }\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n}\n"],"mappings":";AA+FO,IAAM,UAAU;AAAA,EACrB,OAAO,CAAC,QAA4B,KAAa,SAAmB;AAClE,QAAI,CAAC,OAAQ;AACb,WAAO,MAAM,iBAAiB,IAAI,GAAG,GAAG;AAAA,EAC1C;AAAA,EACA,MAAM,CAAC,QAA4B,KAAa,SAAmB;AACjE,QAAI,CAAC,OAAQ;AACb,WAAO,KAAK,iBAAiB,IAAI,GAAG,GAAG;AAAA,EACzC;AAAA,EACA,MAAM,CAAC,QAA4B,KAAa,SAAmB;AACjE,QAAI,CAAC,OAAQ;AACb,WAAO,KAAK,qBAAqB,IAAI,GAAG,GAAG;AAAA,EAC7C;AAAA,EACA,OAAO,CAAC,QAA4B,KAAa,UAAoB;AACnE,QAAI,CAAC,OAAQ;AACb,WAAO,MAAM,sBAAsB,KAAK,GAAG,GAAG;AAAA,EAChD;AACF;AAMA,SAAS,iBAAiB,MAAwC;AAChE,MAAI,SAAS,UAAa,SAAS,MAAM;AACvC,WAAO,CAAC;AAAA,EACV;AACA,MAAI,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI,GAAG;AACpD,WAAO,EAAE,GAAI,KAAiC;AAAA,EAChD;AACA,SAAO,EAAE,KAAK;AAChB;AAOA,SAAS,qBAAqB,MAAwC;AACpE,MAAI,SAAS,UAAa,SAAS,MAAM;AACvC,WAAO,CAAC;AAAA,EACV;AACA,MAAI,gBAAgB,OAAO;AACzB,WAAO,EAAE,KAAK,KAAK;AAAA,EACrB;AACA,MAAI,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI,GAAG;AACpD,WAAO,EAAE,GAAI,KAAiC;AAAA,EAChD;AACA,SAAO,EAAE,KAAK;AAChB;AAOA,SAAS,sBAAsB,OAAyC;AACtE,MAAI,UAAU,UAAa,UAAU,MAAM;AACzC,WAAO,CAAC;AAAA,EACV;AACA,MAAI,iBAAiB,OAAO;AAC1B,WAAO,EAAE,KAAK,MAAM;AAAA,EACtB;AACA,MAAI,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,GAAG;AACtD,WAAO,EAAE,GAAI,MAAkC;AAAA,EACjD;AACA,SAAO,EAAE,KAAK,MAAM;AACtB;","names":[]}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var _chunkMRSGTROWcjs = require('./chunk-MRSGTROW.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
var
|
|
6
|
+
var _chunkHX5NHAJYcjs = require('./chunk-HX5NHAJY.cjs');
|
|
7
7
|
require('./chunk-GS7T56RP.cjs');
|
|
8
8
|
|
|
9
9
|
// src/internal/handler-importer.ts
|
|
@@ -35,7 +35,7 @@ var resolveModulePath = async (modulePath) => {
|
|
|
35
35
|
return modulePath;
|
|
36
36
|
};
|
|
37
37
|
async function importAndRegisterHandlers(modules, logger) {
|
|
38
|
-
|
|
38
|
+
_chunkHX5NHAJYcjs.safeLog.debug(logger, "Importing handler modules", {
|
|
39
39
|
count: modules.length,
|
|
40
40
|
modules: modules.map((m) => m.moduleName)
|
|
41
41
|
});
|
|
@@ -43,7 +43,7 @@ async function importAndRegisterHandlers(modules, logger) {
|
|
|
43
43
|
for (const module of modules) {
|
|
44
44
|
try {
|
|
45
45
|
const resolvedPath = await resolveModulePath(module.absolutePath);
|
|
46
|
-
|
|
46
|
+
_chunkHX5NHAJYcjs.safeLog.debug(logger, "Importing handler module", {
|
|
47
47
|
moduleName: module.moduleName,
|
|
48
48
|
absolutePath: module.absolutePath,
|
|
49
49
|
resolvedPath
|
|
@@ -55,11 +55,11 @@ async function importAndRegisterHandlers(modules, logger) {
|
|
|
55
55
|
_chunkMRSGTROWcjs.registerHandlerModule.call(void 0, resolvedPath, importedModule);
|
|
56
56
|
}
|
|
57
57
|
importedHandlers[module.moduleName] = importedModule;
|
|
58
|
-
|
|
58
|
+
_chunkHX5NHAJYcjs.safeLog.debug(logger, "Handler module imported successfully", {
|
|
59
59
|
moduleName: module.moduleName
|
|
60
60
|
});
|
|
61
61
|
} catch (error) {
|
|
62
|
-
|
|
62
|
+
_chunkHX5NHAJYcjs.safeLog.error(
|
|
63
63
|
logger,
|
|
64
64
|
`Failed to import handler module "${module.moduleName}"`,
|
|
65
65
|
error
|
|
@@ -74,4 +74,4 @@ async function importAndRegisterHandlers(modules, logger) {
|
|
|
74
74
|
|
|
75
75
|
|
|
76
76
|
exports.importAndRegisterHandlers = importAndRegisterHandlers;
|
|
77
|
-
//# sourceMappingURL=handler-importer-
|
|
77
|
+
//# sourceMappingURL=handler-importer-F73SZ2KQ.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/emmett-expressjs-with-openapi/emmett-expressjs-with-openapi/dist/handler-importer-
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/emmett-expressjs-with-openapi/emmett-expressjs-with-openapi/dist/handler-importer-F73SZ2KQ.cjs","../src/internal/handler-importer.ts"],"names":[],"mappings":"AAAA;AACE;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B;AACA;ACCA,uCAAuB;AACvB,wEAAiB;AACjB,0BAA8B;AAO9B,IAAM,iBAAA,EAAmB,CAAC,KAAA,EAAO,MAAA,EAAQ,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,MAAM,CAAA;AAEtE,IAAM,WAAA,EAAa,MAAA,CAAO,QAAA,EAAA,GAAuC;AAC/D,EAAA,IAAI;AACF,IAAA,MAAM,8BAAA,QAAe,CAAA;AACrB,IAAA,OAAO,IAAA;AAAA,EACT,EAAA,UAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF,CAAA;AAEA,IAAM,kBAAA,EAAoB,MAAA,CAAO,UAAA,EAAA,GAAwC;AACvE,EAAA,GAAA,CAAI,MAAM,UAAA,CAAW,UAAU,CAAA,EAAG;AAChC,IAAA,OAAO,UAAA;AAAA,EACT;AAEA,EAAA,GAAA,CAAI,cAAA,CAAK,OAAA,CAAQ,UAAU,CAAA,EAAG;AAC5B,IAAA,OAAO,UAAA;AAAA,EACT;AAEA,EAAA,IAAA,CAAA,MAAW,IAAA,GAAO,gBAAA,EAAkB;AAClC,IAAA,MAAM,UAAA,EAAY,CAAA,EAAA;AACR,IAAA;AACD,MAAA;AACT,IAAA;AACF,EAAA;AAEO,EAAA;AACT;AASsB;AAIN,EAAA;AACG,IAAA;AACE,IAAA;AAClB,EAAA;AAEK,EAAA;AAEe,EAAA;AACf,IAAA;AACI,MAAA;AAEQ,MAAA;AACA,QAAA;AACE,QAAA;AACd,QAAA;AACD,MAAA;AAGe,MAAA;AAGV,MAAA;AAGN,MAAA;AACI,MAAA;AACF,QAAA;AACF,MAAA;AAGiB,MAAA;AAEH,MAAA;AACA,QAAA;AACb,MAAA;AACa,IAAA;AACN,MAAA;AACN,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACU,MAAA;AACR,QAAA;AAGF,MAAA;AACF,IAAA;AACF,EAAA;AAEO,EAAA;AACT;ADpCuB;AACA;AACA","file":"/home/runner/work/emmett-expressjs-with-openapi/emmett-expressjs-with-openapi/dist/handler-importer-F73SZ2KQ.cjs","sourcesContent":[null,"/**\n * Handler module importer.\n *\n * INTERNAL MODULE - Not part of public API.\n *\n * Dynamically imports handler modules and registers them in the ESM resolver cache,\n * enabling automatic handler discovery without manual registration.\n */\n\nimport { access } from 'node:fs/promises';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { type Logger, safeLog } from '../observability';\nimport { registerHandlerModule } from './esm-resolver.js';\nimport type { HandlerModuleInfo } from './openapi-parser.js';\n\nexport type ImportedHandlerModules = Record<string, any>;\n\nconst moduleExtensions = ['.js', '.mjs', '.cjs', '.ts', '.mts', '.cts'];\n\nconst pathExists = async (filePath: string): Promise<boolean> => {\n try {\n await access(filePath);\n return true;\n } catch {\n return false;\n }\n};\n\nconst resolveModulePath = async (modulePath: string): Promise<string> => {\n if (await pathExists(modulePath)) {\n return modulePath;\n }\n\n if (path.extname(modulePath)) {\n return modulePath;\n }\n\n for (const ext of moduleExtensions) {\n const candidate = `${modulePath}${ext}`;\n if (await pathExists(candidate)) {\n return candidate;\n }\n }\n\n return modulePath;\n};\n\n/**\n * Dynamically import and register all handler modules.\n *\n * @param modules - Handler module information from OpenAPI parser\n * @param logger - Optional logger for debug output\n * @returns Object containing all imported modules, keyed by module name\n */\nexport async function importAndRegisterHandlers(\n modules: HandlerModuleInfo[],\n logger?: Logger,\n): Promise<ImportedHandlerModules> {\n safeLog.debug(logger, 'Importing handler modules', {\n count: modules.length,\n modules: modules.map((m) => m.moduleName),\n });\n\n const importedHandlers: ImportedHandlerModules = {};\n\n for (const module of modules) {\n try {\n const resolvedPath = await resolveModulePath(module.absolutePath);\n\n safeLog.debug(logger, 'Importing handler module', {\n moduleName: module.moduleName,\n absolutePath: module.absolutePath,\n resolvedPath,\n });\n\n // Convert to file:// URL for dynamic import\n const fileUrl = pathToFileURL(resolvedPath).href;\n\n // Dynamically import the handler module\n const importedModule = await import(fileUrl);\n\n // Register in ESM resolver cache\n registerHandlerModule(module.absolutePath, importedModule);\n if (resolvedPath !== module.absolutePath) {\n registerHandlerModule(resolvedPath, importedModule);\n }\n\n // Store in result object keyed by module name\n importedHandlers[module.moduleName] = importedModule;\n\n safeLog.debug(logger, 'Handler module imported successfully', {\n moduleName: module.moduleName,\n });\n } catch (error) {\n safeLog.error(\n logger,\n `Failed to import handler module \"${module.moduleName}\"`,\n error,\n );\n throw new Error(\n `Failed to import handler module \"${module.moduleName}\" from ${module.absolutePath}: ${\n (error as Error).message\n }`,\n );\n }\n }\n\n return importedHandlers;\n}\n"]}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-5TC7YUZR.js";
|
|
4
4
|
import {
|
|
5
5
|
safeLog
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-P6WGW2FK.js";
|
|
7
7
|
|
|
8
8
|
// src/internal/handler-importer.ts
|
|
9
9
|
import { access } from "fs/promises";
|
|
@@ -73,4 +73,4 @@ async function importAndRegisterHandlers(modules, logger) {
|
|
|
73
73
|
export {
|
|
74
74
|
importAndRegisterHandlers
|
|
75
75
|
};
|
|
76
|
-
//# sourceMappingURL=handler-importer-
|
|
76
|
+
//# sourceMappingURL=handler-importer-SE6HRBDZ.js.map
|
package/dist/index.cjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var _chunkMRSGTROWcjs = require('./chunk-MRSGTROW.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
var
|
|
6
|
+
var _chunkHX5NHAJYcjs = require('./chunk-HX5NHAJY.cjs');
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
var _chunkGS7T56RPcjs = require('./chunk-GS7T56RP.cjs');
|
|
@@ -27,9 +27,9 @@ var problemDetailsMiddleware = (mapError, logger) => (error, request, response,
|
|
|
27
27
|
if (mapError) problemDetails = mapError(error, request);
|
|
28
28
|
problemDetails = _nullishCoalesce(problemDetails, () => ( defaultErrorToProblemDetailsMapping(error)));
|
|
29
29
|
if (problemDetails.status >= 500) {
|
|
30
|
-
|
|
30
|
+
_chunkHX5NHAJYcjs.safeLog.error(logger, "Server error", error);
|
|
31
31
|
} else {
|
|
32
|
-
|
|
32
|
+
_chunkHX5NHAJYcjs.safeLog.warn(logger, "Client error", error);
|
|
33
33
|
}
|
|
34
34
|
sendProblem(response, problemDetails.status, { problem: problemDetails });
|
|
35
35
|
};
|
|
@@ -66,7 +66,7 @@ var getApplication = async (options) => {
|
|
|
66
66
|
observability
|
|
67
67
|
} = options;
|
|
68
68
|
const logger = _optionalChain([observability, 'optionalAccess', _ => _.logger]);
|
|
69
|
-
|
|
69
|
+
_chunkHX5NHAJYcjs.safeLog.debug(logger, "Initializing Express application", {
|
|
70
70
|
hasApis: !!_optionalChain([apis, 'optionalAccess', _2 => _2.length]),
|
|
71
71
|
hasOpenApiValidator: !!openApiValidator,
|
|
72
72
|
hasPinoHttp: !!pinoHttp
|
|
@@ -85,7 +85,7 @@ var getApplication = async (options) => {
|
|
|
85
85
|
const middleware = provider(options2);
|
|
86
86
|
app.use(middleware);
|
|
87
87
|
} catch (error) {
|
|
88
|
-
|
|
88
|
+
_chunkHX5NHAJYcjs.safeLog.warn(
|
|
89
89
|
logger,
|
|
90
90
|
"Pino HTTP configuration provided but pino-http package is not installed. Install it with: npm install pino-http"
|
|
91
91
|
);
|
|
@@ -107,8 +107,8 @@ var getApplication = async (options) => {
|
|
|
107
107
|
activateESMResolver();
|
|
108
108
|
const handlersBasePath = typeof openApiValidator.operationHandlers === "string" ? openApiValidator.operationHandlers : openApiValidator.operationHandlers.basePath;
|
|
109
109
|
if (handlersBasePath) {
|
|
110
|
-
const { extractHandlerModules } = await Promise.resolve().then(() => _interopRequireWildcard(require("./openapi-parser-
|
|
111
|
-
const { importAndRegisterHandlers } = await Promise.resolve().then(() => _interopRequireWildcard(require("./handler-importer-
|
|
110
|
+
const { extractHandlerModules } = await Promise.resolve().then(() => _interopRequireWildcard(require("./openapi-parser-G4KTMZEZ.cjs")));
|
|
111
|
+
const { importAndRegisterHandlers } = await Promise.resolve().then(() => _interopRequireWildcard(require("./handler-importer-F73SZ2KQ.cjs")));
|
|
112
112
|
const modules = await tracer.startActiveSpan(
|
|
113
113
|
"emmett.openapi.parse_spec",
|
|
114
114
|
async (span) => {
|
|
@@ -142,7 +142,7 @@ var getApplication = async (options) => {
|
|
|
142
142
|
span.setStatus({ code: _api.SpanStatusCode.OK });
|
|
143
143
|
return result;
|
|
144
144
|
} catch (error) {
|
|
145
|
-
|
|
145
|
+
_chunkHX5NHAJYcjs.safeLog.error(logger, "Failed to auto-import handler modules", error);
|
|
146
146
|
span.recordException(error);
|
|
147
147
|
span.setStatus({ code: _api.SpanStatusCode.ERROR });
|
|
148
148
|
throw error;
|
|
@@ -189,7 +189,7 @@ var getApplication = async (options) => {
|
|
|
189
189
|
app.use(middleware);
|
|
190
190
|
}
|
|
191
191
|
} catch (error) {
|
|
192
|
-
|
|
192
|
+
_chunkHX5NHAJYcjs.safeLog.warn(
|
|
193
193
|
logger,
|
|
194
194
|
"OpenAPI validator configuration provided but express-openapi-validator package is not installed. Install it with: npm install express-openapi-validator"
|
|
195
195
|
);
|
|
@@ -206,14 +206,14 @@ var getApplication = async (options) => {
|
|
|
206
206
|
}
|
|
207
207
|
if (!disableProblemDetailsMiddleware)
|
|
208
208
|
app.use(problemDetailsMiddleware(mapError, logger));
|
|
209
|
-
|
|
209
|
+
_chunkHX5NHAJYcjs.safeLog.info(logger, "Express application initialized");
|
|
210
210
|
return app;
|
|
211
211
|
};
|
|
212
212
|
var startAPI = (app, options = { port: 3e3 }) => {
|
|
213
213
|
const { port, logger } = options;
|
|
214
214
|
const server = _http2.default.createServer(app);
|
|
215
215
|
server.on("listening", () => {
|
|
216
|
-
|
|
216
|
+
_chunkHX5NHAJYcjs.safeLog.info(logger, "Server up listening", { port });
|
|
217
217
|
});
|
|
218
218
|
return server.listen(port);
|
|
219
219
|
};
|
|
@@ -582,5 +582,5 @@ var ApiSpecification = {
|
|
|
582
582
|
|
|
583
583
|
|
|
584
584
|
|
|
585
|
-
exports.Accepted = Accepted; exports.ApiE2ESpecification = ApiE2ESpecification; exports.ApiSpecification = ApiSpecification; exports.BadRequest = BadRequest; exports.Conflict = Conflict; exports.Created = Created; exports.DefaultHttpProblemResponseOptions = DefaultHttpProblemResponseOptions; exports.DefaultHttpResponseOptions = DefaultHttpResponseOptions; exports.ETagErrors = ETagErrors; exports.Forbidden = Forbidden; exports.HeaderNames = HeaderNames; exports.HttpProblem = HttpProblem; exports.HttpResponse = HttpResponse; exports.NoContent = NoContent; exports.NotFound = NotFound; exports.OK = OK; exports.PreconditionFailed = PreconditionFailed; exports.WeakETagRegex = WeakETagRegex; exports.createFirebaseAuthSecurityHandlers = createFirebaseAuthSecurityHandlers; exports.createOpenApiValidatorOptions = createOpenApiValidatorOptions; exports.existingStream = existingStream; exports.expect = expect; exports.expectError = expectError; exports.expectNewEvents = expectNewEvents; exports.expectResponse = expectResponse; exports.getApplication = getApplication; exports.getETagFromIfMatch = getETagFromIfMatch; exports.getETagFromIfNotMatch = getETagFromIfNotMatch; exports.getETagValueFromIfMatch = getETagValueFromIfMatch; exports.getWeakETagValue = getWeakETagValue; exports.isOpenApiValidatorAvailable = isOpenApiValidatorAvailable; exports.isWeakETag = isWeakETag; exports.on = on; exports.registerHandlerModule = _chunkMRSGTROWcjs.registerHandlerModule; exports.safeLog =
|
|
585
|
+
exports.Accepted = Accepted; exports.ApiE2ESpecification = ApiE2ESpecification; exports.ApiSpecification = ApiSpecification; exports.BadRequest = BadRequest; exports.Conflict = Conflict; exports.Created = Created; exports.DefaultHttpProblemResponseOptions = DefaultHttpProblemResponseOptions; exports.DefaultHttpResponseOptions = DefaultHttpResponseOptions; exports.ETagErrors = ETagErrors; exports.Forbidden = Forbidden; exports.HeaderNames = HeaderNames; exports.HttpProblem = HttpProblem; exports.HttpResponse = HttpResponse; exports.NoContent = NoContent; exports.NotFound = NotFound; exports.OK = OK; exports.PreconditionFailed = PreconditionFailed; exports.WeakETagRegex = WeakETagRegex; exports.createFirebaseAuthSecurityHandlers = createFirebaseAuthSecurityHandlers; exports.createOpenApiValidatorOptions = createOpenApiValidatorOptions; exports.existingStream = existingStream; exports.expect = expect; exports.expectError = expectError; exports.expectNewEvents = expectNewEvents; exports.expectResponse = expectResponse; exports.getApplication = getApplication; exports.getETagFromIfMatch = getETagFromIfMatch; exports.getETagFromIfNotMatch = getETagFromIfNotMatch; exports.getETagValueFromIfMatch = getETagValueFromIfMatch; exports.getWeakETagValue = getWeakETagValue; exports.isOpenApiValidatorAvailable = isOpenApiValidatorAvailable; exports.isWeakETag = isWeakETag; exports.on = on; exports.registerHandlerModule = _chunkMRSGTROWcjs.registerHandlerModule; exports.safeLog = _chunkHX5NHAJYcjs.safeLog; exports.send = send; exports.sendAccepted = sendAccepted; exports.sendCreated = sendCreated; exports.sendProblem = sendProblem; exports.setETag = setETag; exports.startAPI = startAPI; exports.toWeakETag = toWeakETag; exports.tracedOn = tracedOn;
|
|
586
586
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-5TC7YUZR.js";
|
|
4
4
|
import {
|
|
5
5
|
safeLog
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-P6WGW2FK.js";
|
|
7
7
|
|
|
8
8
|
// src/index.ts
|
|
9
9
|
import "express-async-errors";
|
|
@@ -104,8 +104,8 @@ var getApplication = async (options) => {
|
|
|
104
104
|
activateESMResolver();
|
|
105
105
|
const handlersBasePath = typeof openApiValidator.operationHandlers === "string" ? openApiValidator.operationHandlers : openApiValidator.operationHandlers.basePath;
|
|
106
106
|
if (handlersBasePath) {
|
|
107
|
-
const { extractHandlerModules } = await import("./openapi-parser-
|
|
108
|
-
const { importAndRegisterHandlers } = await import("./handler-importer-
|
|
107
|
+
const { extractHandlerModules } = await import("./openapi-parser-CVIKTGAQ.js");
|
|
108
|
+
const { importAndRegisterHandlers } = await import("./handler-importer-SE6HRBDZ.js");
|
|
109
109
|
const modules = await tracer.startActiveSpan(
|
|
110
110
|
"emmett.openapi.parse_spec",
|
|
111
111
|
async (span) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
safeLog
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-P6WGW2FK.js";
|
|
4
4
|
|
|
5
5
|
// src/internal/openapi-parser.ts
|
|
6
6
|
import { readFile } from "fs/promises";
|
|
@@ -90,4 +90,4 @@ function resolveHandlerPath(basePath, relativePath) {
|
|
|
90
90
|
export {
|
|
91
91
|
extractHandlerModules
|
|
92
92
|
};
|
|
93
|
-
//# sourceMappingURL=openapi-parser-
|
|
93
|
+
//# sourceMappingURL=openapi-parser-CVIKTGAQ.js.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkHX5NHAJYcjs = require('./chunk-HX5NHAJY.cjs');
|
|
4
4
|
require('./chunk-GS7T56RP.cjs');
|
|
5
5
|
|
|
6
6
|
// src/internal/openapi-parser.ts
|
|
7
7
|
var _promises = require('fs/promises');
|
|
8
8
|
var _path = require('path'); var _path2 = _interopRequireDefault(_path);
|
|
9
9
|
async function extractHandlerModules(apiSpec, handlersBasePath, logger) {
|
|
10
|
-
|
|
10
|
+
_chunkHX5NHAJYcjs.safeLog.debug(logger, "Extracting handler modules from OpenAPI spec", {
|
|
11
11
|
apiSpec: typeof apiSpec === "string" ? apiSpec : "<object>",
|
|
12
12
|
handlersBasePath
|
|
13
13
|
});
|
|
@@ -43,14 +43,14 @@ async function extractHandlerModules(apiSpec, handlersBasePath, logger) {
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
const modules = Array.from(handlersMap.values());
|
|
46
|
-
|
|
46
|
+
_chunkHX5NHAJYcjs.safeLog.debug(logger, "Extracted handler modules", {
|
|
47
47
|
count: modules.length,
|
|
48
48
|
modules: modules.map((m) => m.moduleName)
|
|
49
49
|
});
|
|
50
50
|
return modules;
|
|
51
51
|
}
|
|
52
52
|
async function loadOpenApiSpec(filePath, logger) {
|
|
53
|
-
|
|
53
|
+
_chunkHX5NHAJYcjs.safeLog.debug(logger, "Loading OpenAPI spec file", { filePath });
|
|
54
54
|
try {
|
|
55
55
|
const content = await _promises.readFile.call(void 0, filePath, "utf-8");
|
|
56
56
|
const ext = _path2.default.extname(filePath).toLowerCase();
|
|
@@ -65,7 +65,7 @@ async function loadOpenApiSpec(filePath, logger) {
|
|
|
65
65
|
`Unsupported OpenAPI file format: ${ext}. Use .json, .yaml, or .yml`
|
|
66
66
|
);
|
|
67
67
|
}
|
|
68
|
-
|
|
68
|
+
_chunkHX5NHAJYcjs.safeLog.debug(logger, "OpenAPI spec loaded successfully", {
|
|
69
69
|
filePath,
|
|
70
70
|
format: ext
|
|
71
71
|
});
|
|
@@ -91,4 +91,4 @@ function resolveHandlerPath(basePath, relativePath) {
|
|
|
91
91
|
|
|
92
92
|
|
|
93
93
|
exports.extractHandlerModules = extractHandlerModules;
|
|
94
|
-
//# sourceMappingURL=openapi-parser-
|
|
94
|
+
//# sourceMappingURL=openapi-parser-G4KTMZEZ.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/emmett-expressjs-with-openapi/emmett-expressjs-with-openapi/dist/openapi-parser-
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/emmett-expressjs-with-openapi/emmett-expressjs-with-openapi/dist/openapi-parser-G4KTMZEZ.cjs","../src/internal/openapi-parser.ts"],"names":[],"mappings":"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","file":"/home/runner/work/emmett-expressjs-with-openapi/emmett-expressjs-with-openapi/dist/openapi-parser-G4KTMZEZ.cjs","sourcesContent":[null,"/**\n * OpenAPI Parser for handler module discovery.\n *\n * INTERNAL MODULE - Not part of public API.\n *\n * Parses OpenAPI specifications to extract handler module paths from\n * x-eov-operation-handler fields, enabling automatic handler discovery\n * and registration.\n */\n\nimport { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { OpenAPIV3 } from 'express-openapi-validator/dist/framework/types';\nimport { type Logger, safeLog } from '../observability';\n\ntype OpenApiDocument = OpenAPIV3.DocumentV3 | OpenAPIV3.DocumentV3_1;\n\nexport type HandlerModuleInfo = {\n moduleName: string; // e.g., \"shoppingCarts\"\n relativePath: string; // from x-eov-operation-handler\n absolutePath: string; // resolved full path\n operationIds: string[]; // operations using this handler\n};\n\n/**\n * Extract handler modules from OpenAPI specification.\n *\n * @param apiSpec - OpenAPI spec (file path or object)\n * @param handlersBasePath - Base path for handler modules\n * @param logger - Optional logger for debug output\n * @returns Array of handler module information\n */\nexport async function extractHandlerModules(\n apiSpec: string | OpenApiDocument,\n handlersBasePath: string,\n logger?: Logger,\n): Promise<HandlerModuleInfo[]> {\n safeLog.debug(logger, 'Extracting handler modules from OpenAPI spec', {\n apiSpec: typeof apiSpec === 'string' ? apiSpec : '<object>',\n handlersBasePath,\n });\n\n // Load spec if it's a file path\n const spec =\n typeof apiSpec === 'string' ? await loadOpenApiSpec(apiSpec, logger) : apiSpec;\n\n // Validate spec structure\n if (!spec.paths || typeof spec.paths !== 'object') {\n throw new Error('Invalid OpenAPI specification: missing or invalid \"paths\" field');\n }\n\n // Extract handler modules from spec\n const handlersMap = new Map<string, HandlerModuleInfo>();\n\n for (const [pathKey, pathItem] of Object.entries(spec.paths)) {\n if (!pathItem || typeof pathItem !== 'object') continue;\n\n for (const [method, operation] of Object.entries(pathItem)) {\n if (method === 'parameters' || method === 'servers') continue;\n if (!operation || typeof operation !== 'object') continue;\n\n const handlerName = (operation as any)['x-eov-operation-handler'];\n const operationId =\n (operation as any)['x-eov-operation-id'] ||\n (operation as any).operationId;\n\n if (handlerName && typeof handlerName === 'string') {\n const absolutePath = resolveHandlerPath(\n handlersBasePath,\n handlerName,\n );\n\n if (!handlersMap.has(handlerName)) {\n handlersMap.set(handlerName, {\n moduleName: handlerName,\n relativePath: handlerName,\n absolutePath,\n operationIds: [],\n });\n }\n\n if (operationId) {\n handlersMap.get(handlerName)!.operationIds.push(operationId);\n }\n }\n }\n }\n\n const modules = Array.from(handlersMap.values());\n\n safeLog.debug(logger, 'Extracted handler modules', {\n count: modules.length,\n modules: modules.map((m) => m.moduleName),\n });\n\n return modules;\n}\n\n/**\n * Load OpenAPI specification from file.\n */\nasync function loadOpenApiSpec(\n filePath: string,\n logger?: Logger,\n): Promise<OpenApiDocument> {\n safeLog.debug(logger, 'Loading OpenAPI spec file', { filePath });\n try {\n const content = await readFile(filePath, 'utf-8');\n const ext = path.extname(filePath).toLowerCase();\n\n let parsed: OpenApiDocument;\n if (ext === '.json') {\n parsed = JSON.parse(content);\n } else if (ext === '.yaml' || ext === '.yml') {\n // Dynamic import to avoid bundling yaml if not needed\n const yaml = await import('yaml');\n parsed = yaml.parse(content);\n } else {\n throw new Error(\n `Unsupported OpenAPI file format: ${ext}. Use .json, .yaml, or .yml`,\n );\n }\n\n safeLog.debug(logger, 'OpenAPI spec loaded successfully', {\n filePath,\n format: ext,\n });\n\n return parsed;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new Error(`OpenAPI specification file not found: ${filePath}`);\n }\n throw error;\n }\n}\n\n/**\n * Resolve handler module path, preventing path traversal attacks.\n */\nfunction resolveHandlerPath(\n basePath: string,\n relativePath: string,\n): string {\n // Normalize to prevent path traversal\n const normalized = path.normalize(relativePath);\n\n // Resolve absolute path\n const absolutePath = path.resolve(basePath, normalized);\n\n // Ensure path is within basePath (no escape via ../)\n const resolvedBase = path.resolve(basePath);\n if (!absolutePath.startsWith(resolvedBase)) {\n throw new Error(\n `Invalid handler path: \"${relativePath}\" escapes base directory`,\n );\n }\n\n return absolutePath;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@emmett-community/emmett-expressjs-with-openapi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Express.js utilities for Emmett applications that want OpenAPI 3.x validation without pulling the whole Emmett core",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/emmett-expressjs-with-openapi/emmett-expressjs-with-openapi/dist/chunk-FSPH5TRT.cjs","../src/observability.ts"],"names":[],"mappings":"AAAA;AC+FO,IAAM,QAAA,EAAU;AAAA,EACrB,KAAA,EAAO,CAAC,MAAA,EAA4B,GAAA,EAAa,IAAA,EAAA,GAAmB;AAClE,IAAA,GAAA,CAAI,CAAC,MAAA,EAAQ,MAAA;AACb,IAAA,MAAA,CAAO,KAAA,CAAM,gBAAA,CAAiB,IAAI,CAAA,EAAG,GAAG,CAAA;AAAA,EAC1C,CAAA;AAAA,EACA,IAAA,EAAM,CAAC,MAAA,EAA4B,GAAA,EAAa,IAAA,EAAA,GAAmB;AACjE,IAAA,GAAA,CAAI,CAAC,MAAA,EAAQ,MAAA;AACb,IAAA,MAAA,CAAO,IAAA,CAAK,gBAAA,CAAiB,IAAI,CAAA,EAAG,GAAG,CAAA;AAAA,EACzC,CAAA;AAAA,EACA,IAAA,EAAM,CAAC,MAAA,EAA4B,GAAA,EAAa,IAAA,EAAA,GAAmB;AACjE,IAAA,GAAA,CAAI,CAAC,MAAA,EAAQ,MAAA;AACb,IAAA,MAAA,CAAO,IAAA,CAAK,gBAAA,CAAiB,IAAI,CAAA,EAAG,GAAG,CAAA;AAAA,EACzC,CAAA;AAAA,EACA,KAAA,EAAO,CAAC,MAAA,EAA4B,GAAA,EAAa,KAAA,EAAA,GAAoB;AACnE,IAAA,GAAA,CAAI,CAAC,MAAA,EAAQ,MAAA;AACb,IAAA,MAAA,CAAO,KAAA,CAAM,qBAAA,CAAsB,KAAK,CAAA,EAAG,GAAG,CAAA;AAAA,EAChD;AACF,CAAA;AAMA,SAAS,gBAAA,CAAiB,IAAA,EAAwC;AAChE,EAAA,GAAA,CAAI,KAAA,IAAS,KAAA,EAAA,GAAa,KAAA,IAAS,IAAA,EAAM;AACvC,IAAA,OAAO,CAAC,CAAA;AAAA,EACV;AACA,EAAA,GAAA,CAAI,OAAO,KAAA,IAAS,SAAA,GAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,EAAG;AACpD,IAAA,OAAO,EAAE,GAAI,KAAiC,CAAA;AAAA,EAChD;AACA,EAAA,OAAO,EAAE,KAAK,CAAA;AAChB;AAOA,SAAS,qBAAA,CAAsB,KAAA,EAAyC;AACtE,EAAA,GAAA,CAAI,MAAA,IAAU,KAAA,EAAA,GAAa,MAAA,IAAU,IAAA,EAAM;AACzC,IAAA,OAAO,CAAC,CAAA;AAAA,EACV;AACA,EAAA,GAAA,CAAI,MAAA,WAAiB,KAAA,EAAO;AAC1B,IAAA,OAAO,EAAE,GAAA,EAAK,MAAM,CAAA;AAAA,EACtB;AACA,EAAA,GAAA,CAAI,OAAO,MAAA,IAAU,SAAA,GAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACtD,IAAA,OAAO,EAAE,GAAI,MAAkC,CAAA;AAAA,EACjD;AACA,EAAA,OAAO,EAAE,GAAA,EAAK,MAAM,CAAA;AACtB;ADxGA;AACA;AACE;AACF,0BAAC","file":"/home/runner/work/emmett-expressjs-with-openapi/emmett-expressjs-with-openapi/dist/chunk-FSPH5TRT.cjs","sourcesContent":[null,"/**\n * Observability types for emmett-expressjs-with-openapi.\n *\n * This module provides optional logging integration\n * following a \"silent by default\" philosophy.\n */\n\n/**\n * Canonical Logger contract for the Emmett ecosystem.\n *\n * This package defines the canonical Logger interface.\n * Implementations (Pino, Winston, etc.) MUST adapt to this contract.\n * This contract MUST NOT adapt to any specific implementation.\n *\n * Semantic Rules:\n * - context (first parameter): ALWAYS structured data as Record<string, unknown>\n * - message (second parameter): ALWAYS the human-readable log message\n * - The order is NEVER inverted\n * - The (message, data) form is NOT valid for this contract\n *\n * @example\n * ```typescript\n * // Pino - native compatibility\n * import pino from 'pino';\n * const logger = pino();\n * // logger.info({ orderId }, 'Order created') matches our contract\n * ```\n */\nexport interface Logger {\n /**\n * Log debug-level message with structured context.\n * @param context - Structured data to include in the log entry\n * @param message - Optional human-readable message\n */\n debug(context: Record<string, unknown>, message?: string): void;\n\n /**\n * Log info-level message with structured context.\n * @param context - Structured data to include in the log entry\n * @param message - Optional human-readable message\n */\n info(context: Record<string, unknown>, message?: string): void;\n\n /**\n * Log warn-level message with structured context.\n * @param context - Structured data to include in the log entry\n * @param message - Optional human-readable message\n */\n warn(context: Record<string, unknown>, message?: string): void;\n\n /**\n * Log error-level message with structured context.\n * @param context - Structured data to include in the log entry (may include 'err' key)\n * @param message - Optional human-readable message\n */\n error(context: Record<string, unknown>, message?: string): void;\n}\n\n/**\n * Observability configuration options.\n */\nexport type ObservabilityOptions = {\n /**\n * Optional logger instance for diagnostic output.\n * When not provided, the library operates silently.\n *\n * @example\n * ```typescript\n * import pino from 'pino';\n *\n * const logger = pino();\n *\n * const app = await getApplication({\n * observability: { logger },\n * });\n * ```\n */\n logger?: Logger;\n};\n\n/**\n * Internal helper to safely call logger methods.\n *\n * IMPORTANT: safeLog is the ONLY translation point between internal usage\n * and the Logger contract.\n *\n * Internal Usage Pattern:\n * safeLog.info(logger, 'Order created', { orderId: 123 })\n *\n * Translation to Logger Contract:\n * logger.info({ orderId: 123 }, 'Order created')\n *\n * This allows ergonomic internal usage while ensuring all injected loggers\n * receive calls in the canonical (context, message) format.\n */\nexport const safeLog = {\n debug: (logger: Logger | undefined, msg: string, data?: unknown) => {\n if (!logger) return;\n logger.debug(normalizeContext(data), msg);\n },\n info: (logger: Logger | undefined, msg: string, data?: unknown) => {\n if (!logger) return;\n logger.info(normalizeContext(data), msg);\n },\n warn: (logger: Logger | undefined, msg: string, data?: unknown) => {\n if (!logger) return;\n logger.warn(normalizeContext(data), msg);\n },\n error: (logger: Logger | undefined, msg: string, error?: unknown) => {\n if (!logger) return;\n logger.error(normalizeErrorContext(error), msg);\n },\n};\n\n/**\n * Normalize data to context object for regular log methods.\n * Creates a shallow copy to avoid accidental mutation of the original object.\n */\nfunction normalizeContext(data: unknown): Record<string, unknown> {\n if (data === undefined || data === null) {\n return {};\n }\n if (typeof data === 'object' && !Array.isArray(data)) {\n return { ...(data as Record<string, unknown>) };\n }\n return { data };\n}\n\n/**\n * Normalize error to context object for error log method.\n * Uses 'err' key for Pino compatibility (Pino serializes Error objects on 'err' key).\n * Creates a shallow copy to avoid accidental mutation of the original object.\n */\nfunction normalizeErrorContext(error: unknown): Record<string, unknown> {\n if (error === undefined || error === null) {\n return {};\n }\n if (error instanceof Error) {\n return { err: error };\n }\n if (typeof error === 'object' && !Array.isArray(error)) {\n return { ...(error as Record<string, unknown>) };\n }\n return { err: error };\n}\n"]}
|
|
File without changes
|
|
File without changes
|