@emmett-community/emmett-expressjs-with-openapi 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +100 -0
- package/dist/chunk-5TC7YUZR.js +38 -0
- package/dist/chunk-5TC7YUZR.js.map +1 -0
- package/dist/chunk-GS7T56RP.cjs +8 -0
- package/dist/chunk-GS7T56RP.cjs.map +1 -0
- package/dist/chunk-MRSGTROW.cjs +42 -0
- package/dist/chunk-MRSGTROW.cjs.map +1 -0
- package/dist/esm-resolver-I5MW2PIQ.cjs +10 -0
- package/dist/esm-resolver-I5MW2PIQ.cjs.map +1 -0
- package/dist/esm-resolver-ZL5JTVDP.js +9 -0
- package/dist/esm-resolver-ZL5JTVDP.js.map +1 -0
- package/dist/handler-importer-4BVBIZX3.cjs +27 -0
- package/dist/handler-importer-4BVBIZX3.cjs.map +1 -0
- package/dist/handler-importer-OJGFQON5.js +26 -0
- package/dist/handler-importer-OJGFQON5.js.map +1 -0
- package/dist/index.cjs +428 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +440 -0
- package/dist/index.d.ts +440 -0
- package/dist/index.js +425 -0
- package/dist/index.js.map +1 -0
- package/dist/openapi-parser-6EGURSGG.js +73 -0
- package/dist/openapi-parser-6EGURSGG.js.map +1 -0
- package/dist/openapi-parser-KI7BS3DC.cjs +75 -0
- package/dist/openapi-parser-KI7BS3DC.cjs.map +1 -0
- package/package.json +81 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Andre X Costa
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# @emmett-community/emmett-expressjs-with-openapi
|
|
2
|
+
|
|
3
|
+
Express.js utilities for Emmett applications that want OpenAPI 3.x validation without pulling the whole Emmett core. This package wires [`express-openapi-validator`](https://github.com/cdimascio/express-openapi-validator) into the Emmett application builder so you can validate requests, responses, security handlers, file uploads, and formats from a single OpenAPI document.
|
|
4
|
+
|
|
5
|
+
## Why this package?
|
|
6
|
+
|
|
7
|
+
- Built as a standalone module extracted from the original `@event-driven-io/emmett` repo so it can evolve independently.
|
|
8
|
+
- Keeps the OpenAPI document as the single source of truth across manual routers, validation, and `operationHandlers`.
|
|
9
|
+
- Ships with batteries included: problem-details error handling, helpers for tests, and examples for real-world setups.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @emmett-community/emmett-expressjs-with-openapi
|
|
15
|
+
npm install express-openapi-validator # optional peer dependency
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Other peer requirements (`express`, `@event-driven-io/emmett`, etc.) follow the versions listed in `package.json`.
|
|
19
|
+
|
|
20
|
+
## Quick start
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import {
|
|
24
|
+
getApplication,
|
|
25
|
+
createOpenApiValidatorOptions,
|
|
26
|
+
} from '@emmett-community/emmett-expressjs-with-openapi';
|
|
27
|
+
|
|
28
|
+
const app = getApplication({
|
|
29
|
+
apis: [myApi],
|
|
30
|
+
openApiValidator: createOpenApiValidatorOptions('./openapi.yaml', {
|
|
31
|
+
validateRequests: true,
|
|
32
|
+
validateResponses: process.env.NODE_ENV === 'development',
|
|
33
|
+
}),
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Prefer to parse the spec once and share it? Load the `.yml` document manually and reuse it for routing, validation, and automatic `operationHandlers`.
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import path from 'node:path';
|
|
41
|
+
import { readFileSync } from 'node:fs';
|
|
42
|
+
import { parse } from 'yaml';
|
|
43
|
+
|
|
44
|
+
const spec = parse(readFileSync(new URL('./openapi.yml', import.meta.url), 'utf-8'));
|
|
45
|
+
|
|
46
|
+
const app = getApplication({
|
|
47
|
+
apis: [usersApi],
|
|
48
|
+
openApiValidator: createOpenApiValidatorOptions(spec, {
|
|
49
|
+
operationHandlers: path.join(path.dirname(import.meta.url), './handlers'),
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Configuration highlights
|
|
55
|
+
|
|
56
|
+
`createOpenApiValidatorOptions` forwards every option from `express-openapi-validator`, so you can:
|
|
57
|
+
|
|
58
|
+
- Enable/disable request or response validation, including per-field tweaks (coercion, unknown query params, removing additional fields, etc.).
|
|
59
|
+
- Register custom security handlers with `validateSecurity.handlers`.
|
|
60
|
+
- Serve the parsed spec via `serveSpec`, configure file upload limits, ignore health-check routes, or validate the spec itself.
|
|
61
|
+
- Reuse `$ref` parsing, custom formats, and file upload middleware exactly as in the upstream validator.
|
|
62
|
+
|
|
63
|
+
Head to [`docs/openapi-validation.md`](docs/openapi-validation.md) for the full matrix of options, extended explanations, and complete examples. Keeping that document allows us to document advanced scenarios without bloating the README.
|
|
64
|
+
|
|
65
|
+
## Examples
|
|
66
|
+
|
|
67
|
+
Working examples live under `examples/`:
|
|
68
|
+
|
|
69
|
+
- `examples/shopping-cart` – feature-complete Emmett sample (business logic, memory store/publisher, security handlers, OpenAPI file, unit/int/e2e tests, `.http` scripts).
|
|
70
|
+
- Legacy quick starts:
|
|
71
|
+
- `examples/basic` – manual routes + validation (minimal scaffolding).
|
|
72
|
+
- `examples/with-security` – standalone security handler demo.
|
|
73
|
+
- `examples/operation-handlers` – barebones `operationHandlers` showcase.
|
|
74
|
+
|
|
75
|
+
## Tests
|
|
76
|
+
|
|
77
|
+
The package includes comprehensive test coverage:
|
|
78
|
+
|
|
79
|
+
- **Unit tests** (`test/unit/`) - Utilities for ETag handling, error mapping
|
|
80
|
+
- **Integration tests** (`test/integration/`) - Basic routing, OpenAPI validation, operation handlers, optimistic concurrency
|
|
81
|
+
- **E2E tests** (`test/e2e/`) - End-to-end workflows for all features
|
|
82
|
+
|
|
83
|
+
Run `npm test` to execute the whole suite (unit + integration + e2e) or use:
|
|
84
|
+
|
|
85
|
+
- `npm run test:unit` - Unit tests only
|
|
86
|
+
- `npm run test:int` - Integration tests only
|
|
87
|
+
- `npm run test:e2e` - E2E tests only
|
|
88
|
+
|
|
89
|
+
## Documentation
|
|
90
|
+
|
|
91
|
+
- **Guide:** [`docs/openapi-validation.md`](docs/openapi-validation.md) – authoritative reference for configuration, advanced usage, and troubleshooting.
|
|
92
|
+
- **Emmett docs:** <https://event-driven-io.github.io/emmett/>
|
|
93
|
+
|
|
94
|
+
## Contributing
|
|
95
|
+
|
|
96
|
+
Issues and PRs are welcome! Please open a discussion or ticket if you are unsure about the direction of a change before coding.
|
|
97
|
+
|
|
98
|
+
## License
|
|
99
|
+
|
|
100
|
+
MIT
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// src/internal/esm-resolver.ts
|
|
2
|
+
import { createRequire } from "module";
|
|
3
|
+
import path from "path";
|
|
4
|
+
var isPatched = false;
|
|
5
|
+
var moduleCache = /* @__PURE__ */ new Map();
|
|
6
|
+
var registerHandlerModule = (modulePath, moduleExports) => {
|
|
7
|
+
moduleCache.set(modulePath, moduleExports);
|
|
8
|
+
};
|
|
9
|
+
var activateESMResolver = () => {
|
|
10
|
+
if (isPatched) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const require2 = createRequire(import.meta.url);
|
|
14
|
+
const Module = require2("module");
|
|
15
|
+
const originalLoad = Module._load;
|
|
16
|
+
Module._load = function(request, parent, isMain) {
|
|
17
|
+
const caller = parent?.filename;
|
|
18
|
+
const isValidatorLoading = caller?.includes("express-openapi-validator");
|
|
19
|
+
const isHandlerModule = request.includes("handlers");
|
|
20
|
+
if (isValidatorLoading && isHandlerModule) {
|
|
21
|
+
const absolutePath = path.isAbsolute(request) ? request : path.resolve(path.dirname(caller), request);
|
|
22
|
+
if (moduleCache.has(absolutePath)) {
|
|
23
|
+
return moduleCache.get(absolutePath);
|
|
24
|
+
}
|
|
25
|
+
throw new Error(
|
|
26
|
+
`Handler module not registered: ${absolutePath}. Make sure initializeHandlers imports and registers the module.`
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
return originalLoad.call(this, request, parent, isMain);
|
|
30
|
+
};
|
|
31
|
+
isPatched = true;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export {
|
|
35
|
+
registerHandlerModule,
|
|
36
|
+
activateESMResolver
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=chunk-5TC7YUZR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/internal/esm-resolver.ts"],"sourcesContent":["/**\n * ESM Resolver for express-openapi-validator operation handlers.\n *\n * INTERNAL MODULE - Not part of public API.\n *\n * PROBLEM:\n * When using TypeScript runtime (tsx) with express-openapi-validator's operationHandlers:\n * - Our code uses `import()` to load handlers (ESM)\n * - express-openapi-validator uses `require()` to load handlers (CJS)\n * - Node.js maintains separate module caches for ESM and CJS\n * - This creates TWO separate instances of the same handler module\n * - Dependencies injected via module-level variables in one instance don't reach the other\n *\n * SOLUTION:\n * This module monkey-patches Module.prototype.require to intercept when\n * express-openapi-validator loads operation handlers and forces it to use\n * dynamic import() instead of require(). This ensures both sides share the\n * same ESM module instance, allowing module-level variables to work correctly.\n *\n * USAGE:\n * This module is automatically activated by getApplication() when operationHandlers\n * are configured. Applications don't need to import or configure anything.\n *\n * LIMITATIONS:\n * - Relies on heuristic detection (caller path includes 'express-openapi-validator')\n * - May break if express-openapi-validator changes its internal loading mechanism\n * - Adds \"magic\" behavior that may not be immediately obvious to developers\n *\n * FUTURE:\n * If express-openapi-validator migrates to native ESM, this resolver becomes\n * unnecessary and will safely become a no-op.\n */\n\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\n\nlet isPatched = false;\nconst moduleCache = new Map<string, any>();\n\n/**\n * Registers a pre-loaded ESM module so it can be returned synchronously\n * when express-openapi-validator tries to require() it.\n */\nexport const registerHandlerModule = (modulePath: string, moduleExports: any): void => {\n moduleCache.set(modulePath, moduleExports);\n};\n\n/**\n * Activates the ESM resolver for express-openapi-validator handler loading.\n */\nexport const activateESMResolver = (): void => {\n if (isPatched) {\n return;\n }\n\n const require = createRequire(import.meta.url);\n const Module = require('module');\n const originalLoad = Module._load;\n\n Module._load = function (request: string, parent: any, isMain: boolean) {\n const caller = parent?.filename;\n const isValidatorLoading = caller?.includes('express-openapi-validator');\n const isHandlerModule = request.includes('handlers');\n\n if (isValidatorLoading && isHandlerModule) {\n const absolutePath = path.isAbsolute(request)\n ? request\n : path.resolve(path.dirname(caller), request);\n\n // Check if we have this module pre-registered\n if (moduleCache.has(absolutePath)) {\n return moduleCache.get(absolutePath);\n }\n\n throw new Error(\n `Handler module not registered: ${absolutePath}. ` +\n `Make sure initializeHandlers imports and registers the module.`\n );\n }\n\n return originalLoad.call(this, request, parent, isMain);\n };\n\n isPatched = true;\n};\n"],"mappings":";AAiCA,SAAS,qBAAqB;AAC9B,OAAO,UAAU;AAEjB,IAAI,YAAY;AAChB,IAAM,cAAc,oBAAI,IAAiB;AAMlC,IAAM,wBAAwB,CAAC,YAAoB,kBAA6B;AACrF,cAAY,IAAI,YAAY,aAAa;AAC3C;AAKO,IAAM,sBAAsB,MAAY;AAC7C,MAAI,WAAW;AACb;AAAA,EACF;AAEA,QAAMA,WAAU,cAAc,YAAY,GAAG;AAC7C,QAAM,SAASA,SAAQ,QAAQ;AAC/B,QAAM,eAAe,OAAO;AAE5B,SAAO,QAAQ,SAAU,SAAiB,QAAa,QAAiB;AACtE,UAAM,SAAS,QAAQ;AACvB,UAAM,qBAAqB,QAAQ,SAAS,2BAA2B;AACvE,UAAM,kBAAkB,QAAQ,SAAS,UAAU;AAEnD,QAAI,sBAAsB,iBAAiB;AACzC,YAAM,eAAe,KAAK,WAAW,OAAO,IACxC,UACA,KAAK,QAAQ,KAAK,QAAQ,MAAM,GAAG,OAAO;AAG9C,UAAI,YAAY,IAAI,YAAY,GAAG;AACjC,eAAO,YAAY,IAAI,YAAY;AAAA,MACrC;AAEA,YAAM,IAAI;AAAA,QACR,kCAAkC,YAAY;AAAA,MAEhD;AAAA,IACF;AAEA,WAAO,aAAa,KAAK,MAAM,SAAS,QAAQ,MAAM;AAAA,EACxD;AAEA,cAAY;AACd;","names":["require"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// node_modules/tsup/assets/cjs_shims.js
|
|
2
|
+
var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
|
|
3
|
+
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
exports.importMetaUrl = importMetaUrl;
|
|
8
|
+
//# sourceMappingURL=chunk-GS7T56RP.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/axcosta/Git/pessoal/oss/emmett-community/emmett-expressjs-with-openapi/dist/chunk-GS7T56RP.cjs","../node_modules/tsup/assets/cjs_shims.js"],"names":[],"mappings":"AAAA;ACKA,IAAM,iBAAA,EAAmB,CAAA,EAAA,GACvB,OAAO,SAAA,IAAa,YAAA,EAChB,IAAI,GAAA,CAAI,CAAA,KAAA,EAAQ,UAAU,CAAA,CAAA;AAK8B;ADT4B;AACA;AACA;AACA","file":"/Users/axcosta/Git/pessoal/oss/emmett-community/emmett-expressjs-with-openapi/dist/chunk-GS7T56RP.cjs","sourcesContent":[null,"// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n"]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
|
|
3
|
+
var _chunkGS7T56RPcjs = require('./chunk-GS7T56RP.cjs');
|
|
4
|
+
|
|
5
|
+
// src/internal/esm-resolver.ts
|
|
6
|
+
var _module = require('module');
|
|
7
|
+
var _path = require('path'); var _path2 = _interopRequireDefault(_path);
|
|
8
|
+
var isPatched = false;
|
|
9
|
+
var moduleCache = /* @__PURE__ */ new Map();
|
|
10
|
+
var registerHandlerModule = (modulePath, moduleExports) => {
|
|
11
|
+
moduleCache.set(modulePath, moduleExports);
|
|
12
|
+
};
|
|
13
|
+
var activateESMResolver = () => {
|
|
14
|
+
if (isPatched) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const require2 = _module.createRequire.call(void 0, _chunkGS7T56RPcjs.importMetaUrl);
|
|
18
|
+
const Module = require2("module");
|
|
19
|
+
const originalLoad = Module._load;
|
|
20
|
+
Module._load = function(request, parent, isMain) {
|
|
21
|
+
const caller = _optionalChain([parent, 'optionalAccess', _ => _.filename]);
|
|
22
|
+
const isValidatorLoading = _optionalChain([caller, 'optionalAccess', _2 => _2.includes, 'call', _3 => _3("express-openapi-validator")]);
|
|
23
|
+
const isHandlerModule = request.includes("handlers");
|
|
24
|
+
if (isValidatorLoading && isHandlerModule) {
|
|
25
|
+
const absolutePath = _path2.default.isAbsolute(request) ? request : _path2.default.resolve(_path2.default.dirname(caller), request);
|
|
26
|
+
if (moduleCache.has(absolutePath)) {
|
|
27
|
+
return moduleCache.get(absolutePath);
|
|
28
|
+
}
|
|
29
|
+
throw new Error(
|
|
30
|
+
`Handler module not registered: ${absolutePath}. Make sure initializeHandlers imports and registers the module.`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return originalLoad.call(this, request, parent, isMain);
|
|
34
|
+
};
|
|
35
|
+
isPatched = true;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
exports.registerHandlerModule = registerHandlerModule; exports.activateESMResolver = activateESMResolver;
|
|
42
|
+
//# sourceMappingURL=chunk-MRSGTROW.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/axcosta/Git/pessoal/oss/emmett-community/emmett-expressjs-with-openapi/dist/chunk-MRSGTROW.cjs","../src/internal/esm-resolver.ts"],"names":["require"],"mappings":"AAAA;AACE;AACF,wDAA6B;AAC7B;AACA;AC6BA,gCAA8B;AAC9B,wEAAiB;AAEjB,IAAI,UAAA,EAAY,KAAA;AAChB,IAAM,YAAA,kBAAc,IAAI,GAAA,CAAiB,CAAA;AAMlC,IAAM,sBAAA,EAAwB,CAAC,UAAA,EAAoB,aAAA,EAAA,GAA6B;AACrF,EAAA,WAAA,CAAY,GAAA,CAAI,UAAA,EAAY,aAAa,CAAA;AAC3C,CAAA;AAKO,IAAM,oBAAA,EAAsB,CAAA,EAAA,GAAY;AAC7C,EAAA,GAAA,CAAI,SAAA,EAAW;AACb,IAAA,MAAA;AAAA,EACF;AAEA,EAAA,MAAMA,SAAAA,EAAU,mCAAA,+BAA6B,CAAA;AAC7C,EAAA,MAAM,OAAA,EAASA,QAAAA,CAAQ,QAAQ,CAAA;AAC/B,EAAA,MAAM,aAAA,EAAe,MAAA,CAAO,KAAA;AAE5B,EAAA,MAAA,CAAO,MAAA,EAAQ,QAAA,CAAU,OAAA,EAAiB,MAAA,EAAa,MAAA,EAAiB;AACtE,IAAA,MAAM,OAAA,kBAAS,MAAA,2BAAQ,UAAA;AACvB,IAAA,MAAM,mBAAA,kBAAqB,MAAA,6BAAQ,QAAA,mBAAS,2BAA2B,GAAA;AACvE,IAAA,MAAM,gBAAA,EAAkB,OAAA,CAAQ,QAAA,CAAS,UAAU,CAAA;AAEnD,IAAA,GAAA,CAAI,mBAAA,GAAsB,eAAA,EAAiB;AACzC,MAAA,MAAM,aAAA,EAAe,cAAA,CAAK,UAAA,CAAW,OAAO,EAAA,EACxC,QAAA,EACA,cAAA,CAAK,OAAA,CAAQ,cAAA,CAAK,OAAA,CAAQ,MAAM,CAAA,EAAG,OAAO,CAAA;AAG9C,MAAA,GAAA,CAAI,WAAA,CAAY,GAAA,CAAI,YAAY,CAAA,EAAG;AACjC,QAAA,OAAO,WAAA,CAAY,GAAA,CAAI,YAAY,CAAA;AAAA,MACrC;AAEA,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,+BAAA,EAAkC,YAAY,CAAA,gEAAA;AAAA,MAEhD,CAAA;AAAA,IACF;AAEA,IAAA,OAAO,YAAA,CAAa,IAAA,CAAK,IAAA,EAAM,OAAA,EAAS,MAAA,EAAQ,MAAM,CAAA;AAAA,EACxD,CAAA;AAEA,EAAA,UAAA,EAAY,IAAA;AACd,CAAA;ADhDA;AACA;AACE;AACA;AACF,yGAAC","file":"/Users/axcosta/Git/pessoal/oss/emmett-community/emmett-expressjs-with-openapi/dist/chunk-MRSGTROW.cjs","sourcesContent":[null,"/**\n * ESM Resolver for express-openapi-validator operation handlers.\n *\n * INTERNAL MODULE - Not part of public API.\n *\n * PROBLEM:\n * When using TypeScript runtime (tsx) with express-openapi-validator's operationHandlers:\n * - Our code uses `import()` to load handlers (ESM)\n * - express-openapi-validator uses `require()` to load handlers (CJS)\n * - Node.js maintains separate module caches for ESM and CJS\n * - This creates TWO separate instances of the same handler module\n * - Dependencies injected via module-level variables in one instance don't reach the other\n *\n * SOLUTION:\n * This module monkey-patches Module.prototype.require to intercept when\n * express-openapi-validator loads operation handlers and forces it to use\n * dynamic import() instead of require(). This ensures both sides share the\n * same ESM module instance, allowing module-level variables to work correctly.\n *\n * USAGE:\n * This module is automatically activated by getApplication() when operationHandlers\n * are configured. Applications don't need to import or configure anything.\n *\n * LIMITATIONS:\n * - Relies on heuristic detection (caller path includes 'express-openapi-validator')\n * - May break if express-openapi-validator changes its internal loading mechanism\n * - Adds \"magic\" behavior that may not be immediately obvious to developers\n *\n * FUTURE:\n * If express-openapi-validator migrates to native ESM, this resolver becomes\n * unnecessary and will safely become a no-op.\n */\n\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\n\nlet isPatched = false;\nconst moduleCache = new Map<string, any>();\n\n/**\n * Registers a pre-loaded ESM module so it can be returned synchronously\n * when express-openapi-validator tries to require() it.\n */\nexport const registerHandlerModule = (modulePath: string, moduleExports: any): void => {\n moduleCache.set(modulePath, moduleExports);\n};\n\n/**\n * Activates the ESM resolver for express-openapi-validator handler loading.\n */\nexport const activateESMResolver = (): void => {\n if (isPatched) {\n return;\n }\n\n const require = createRequire(import.meta.url);\n const Module = require('module');\n const originalLoad = Module._load;\n\n Module._load = function (request: string, parent: any, isMain: boolean) {\n const caller = parent?.filename;\n const isValidatorLoading = caller?.includes('express-openapi-validator');\n const isHandlerModule = request.includes('handlers');\n\n if (isValidatorLoading && isHandlerModule) {\n const absolutePath = path.isAbsolute(request)\n ? request\n : path.resolve(path.dirname(caller), request);\n\n // Check if we have this module pre-registered\n if (moduleCache.has(absolutePath)) {\n return moduleCache.get(absolutePath);\n }\n\n throw new Error(\n `Handler module not registered: ${absolutePath}. ` +\n `Make sure initializeHandlers imports and registers the module.`\n );\n }\n\n return originalLoad.call(this, request, parent, isMain);\n };\n\n isPatched = true;\n};\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkMRSGTROWcjs = require('./chunk-MRSGTROW.cjs');
|
|
5
|
+
require('./chunk-GS7T56RP.cjs');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
exports.activateESMResolver = _chunkMRSGTROWcjs.activateESMResolver; exports.registerHandlerModule = _chunkMRSGTROWcjs.registerHandlerModule;
|
|
10
|
+
//# sourceMappingURL=esm-resolver-I5MW2PIQ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/axcosta/Git/pessoal/oss/emmett-community/emmett-expressjs-with-openapi/dist/esm-resolver-I5MW2PIQ.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACA;AACF,6IAAC","file":"/Users/axcosta/Git/pessoal/oss/emmett-community/emmett-expressjs-with-openapi/dist/esm-resolver-I5MW2PIQ.cjs"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,27 @@
|
|
|
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; } }
|
|
2
|
+
|
|
3
|
+
var _chunkMRSGTROWcjs = require('./chunk-MRSGTROW.cjs');
|
|
4
|
+
require('./chunk-GS7T56RP.cjs');
|
|
5
|
+
|
|
6
|
+
// src/internal/handler-importer.ts
|
|
7
|
+
var _url = require('url');
|
|
8
|
+
async function importAndRegisterHandlers(modules) {
|
|
9
|
+
const importedHandlers = {};
|
|
10
|
+
for (const module of modules) {
|
|
11
|
+
try {
|
|
12
|
+
const fileUrl = _url.pathToFileURL.call(void 0, module.absolutePath).href;
|
|
13
|
+
const importedModule = await Promise.resolve().then(() => _interopRequireWildcard(require(fileUrl)));
|
|
14
|
+
_chunkMRSGTROWcjs.registerHandlerModule.call(void 0, module.absolutePath, importedModule);
|
|
15
|
+
importedHandlers[module.moduleName] = importedModule;
|
|
16
|
+
} catch (error) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
`Failed to import handler module "${module.moduleName}" from ${module.absolutePath}: ${error.message}`
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return importedHandlers;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
exports.importAndRegisterHandlers = importAndRegisterHandlers;
|
|
27
|
+
//# sourceMappingURL=handler-importer-4BVBIZX3.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/axcosta/Git/pessoal/oss/emmett-community/emmett-expressjs-with-openapi/dist/handler-importer-4BVBIZX3.cjs","../src/internal/handler-importer.ts"],"names":[],"mappings":"AAAA;AACE;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B;AACA;ACIA,0BAA8B;AAY9B,MAAA,SAAsB,yBAAA,CACpB,OAAA,EACiC;AACjC,EAAA,MAAM,iBAAA,EAA2C,CAAC,CAAA;AAElD,EAAA,IAAA,CAAA,MAAW,OAAA,GAAU,OAAA,EAAS;AAC5B,IAAA,IAAI;AAEF,MAAA,MAAM,QAAA,EAAU,gCAAA,MAAc,CAAO,YAAY,CAAA,CAAE,IAAA;AAGnD,MAAA,MAAM,eAAA,EAAiB,MAAM,4DAAA,CAAO,OAAA,GAAA;AAGpC,MAAA,qDAAA,MAAsB,CAAO,YAAA,EAAc,cAAc,CAAA;AAGzD,MAAA,gBAAA,CAAiB,MAAA,CAAO,UAAU,EAAA,EAAI,cAAA;AAAA,IACxC,EAAA,MAAA,CAAS,KAAA,EAAO;AACd,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,iCAAA,EAAoC,MAAA,CAAO,UAAU,CAAA,OAAA,EAAU,MAAA,CAAO,YAAY,CAAA,EAAA,EAC/E,KAAA,CAAgB,OACnB,CAAA;AAAA,MAAA;AACF,IAAA;AACF,EAAA;AAGF,EAAA;AACF;AD1BA;AACA;AACA","file":"/Users/axcosta/Git/pessoal/oss/emmett-community/emmett-expressjs-with-openapi/dist/handler-importer-4BVBIZX3.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 { pathToFileURL } from 'node:url';\nimport { registerHandlerModule } from './esm-resolver.js';\nimport type { HandlerModuleInfo } from './openapi-parser.js';\n\nexport type ImportedHandlerModules = Record<string, any>;\n\n/**\n * Dynamically import and register all handler modules.\n *\n * @param modules - Handler module information from OpenAPI parser\n * @returns Object containing all imported modules, keyed by module name\n */\nexport async function importAndRegisterHandlers(\n modules: HandlerModuleInfo[],\n): Promise<ImportedHandlerModules> {\n const importedHandlers: ImportedHandlerModules = {};\n\n for (const module of modules) {\n try {\n // Convert to file:// URL for dynamic import\n const fileUrl = pathToFileURL(module.absolutePath).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\n // Store in result object keyed by module name\n importedHandlers[module.moduleName] = importedModule;\n } catch (error) {\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"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {
|
|
2
|
+
registerHandlerModule
|
|
3
|
+
} from "./chunk-5TC7YUZR.js";
|
|
4
|
+
|
|
5
|
+
// src/internal/handler-importer.ts
|
|
6
|
+
import { pathToFileURL } from "url";
|
|
7
|
+
async function importAndRegisterHandlers(modules) {
|
|
8
|
+
const importedHandlers = {};
|
|
9
|
+
for (const module of modules) {
|
|
10
|
+
try {
|
|
11
|
+
const fileUrl = pathToFileURL(module.absolutePath).href;
|
|
12
|
+
const importedModule = await import(fileUrl);
|
|
13
|
+
registerHandlerModule(module.absolutePath, importedModule);
|
|
14
|
+
importedHandlers[module.moduleName] = importedModule;
|
|
15
|
+
} catch (error) {
|
|
16
|
+
throw new Error(
|
|
17
|
+
`Failed to import handler module "${module.moduleName}" from ${module.absolutePath}: ${error.message}`
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return importedHandlers;
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
importAndRegisterHandlers
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=handler-importer-OJGFQON5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/internal/handler-importer.ts"],"sourcesContent":["/**\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 { pathToFileURL } from 'node:url';\nimport { registerHandlerModule } from './esm-resolver.js';\nimport type { HandlerModuleInfo } from './openapi-parser.js';\n\nexport type ImportedHandlerModules = Record<string, any>;\n\n/**\n * Dynamically import and register all handler modules.\n *\n * @param modules - Handler module information from OpenAPI parser\n * @returns Object containing all imported modules, keyed by module name\n */\nexport async function importAndRegisterHandlers(\n modules: HandlerModuleInfo[],\n): Promise<ImportedHandlerModules> {\n const importedHandlers: ImportedHandlerModules = {};\n\n for (const module of modules) {\n try {\n // Convert to file:// URL for dynamic import\n const fileUrl = pathToFileURL(module.absolutePath).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\n // Store in result object keyed by module name\n importedHandlers[module.moduleName] = importedModule;\n } catch (error) {\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"],"mappings":";;;;;AASA,SAAS,qBAAqB;AAY9B,eAAsB,0BACpB,SACiC;AACjC,QAAM,mBAA2C,CAAC;AAElD,aAAW,UAAU,SAAS;AAC5B,QAAI;AAEF,YAAM,UAAU,cAAc,OAAO,YAAY,EAAE;AAGnD,YAAM,iBAAiB,MAAM,OAAO;AAGpC,4BAAsB,OAAO,cAAc,cAAc;AAGzD,uBAAiB,OAAO,UAAU,IAAI;AAAA,IACxC,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR,oCAAoC,OAAO,UAAU,UAAU,OAAO,YAAY,KAC/E,MAAgB,OACnB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;","names":[]}
|