node-esm-mock 0.1.1 → 0.2.1
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/index.d.ts +3 -3
- package/dist/index.js +66 -77
- package/package.json +4 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
export declare function mock(
|
|
3
|
-
for<T = any>(specifier: string): Promise<T>;
|
|
1
|
+
export declare const mocksFor: Map<string, Map<string, any>>;
|
|
2
|
+
export declare function mock(modules?: Record<string, any>): {
|
|
3
|
+
for<T = any>(specifier: string, keep?: boolean): Promise<T>;
|
|
4
4
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,94 +1,83 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
1
10
|
import { registerHooks } from 'node:module';
|
|
2
|
-
const mockedModuleExports = new Map();
|
|
3
|
-
let mainImportURL = import.meta.url;
|
|
4
11
|
registerHooks({
|
|
5
|
-
resolve(specifier, context,
|
|
6
|
-
var _a;
|
|
7
|
-
|
|
8
|
-
if (!((_a = context.parentURL) === null || _a === void 0 ? void 0 : _a.startsWith('
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
resolve(specifier, context, nextResolver) {
|
|
13
|
+
var _a, _b;
|
|
14
|
+
// If the parentURL is not a file and contains a query, it means it's a mocked module, so we should ignore the parentURL to avoid issues with resolving the original module.
|
|
15
|
+
if (!((_a = context.parentURL) === null || _a === void 0 ? void 0 : _a.startsWith('file:')) && ((_b = context.parentURL) === null || _b === void 0 ? void 0 : _b.includes('?'))) {
|
|
16
|
+
context.parentURL = undefined;
|
|
17
|
+
}
|
|
18
|
+
const resolved = nextResolver(specifier, context);
|
|
19
|
+
const mocksForSpecifier = mocksFor.get(specifier);
|
|
20
|
+
if (mocksForSpecifier) {
|
|
21
|
+
mocksFor.set(resolved.url, mocksForSpecifier);
|
|
22
|
+
}
|
|
23
|
+
if (context.parentURL) {
|
|
24
|
+
const mocksForParentURL = mocksFor.get(context.parentURL);
|
|
25
|
+
if (mocksForParentURL) {
|
|
26
|
+
const scope = context.parentURL.split('?')[1];
|
|
27
|
+
const resolvedUrl = `${resolved.url}?${scope}`;
|
|
28
|
+
if (mocksForParentURL.has(resolvedUrl)) {
|
|
29
|
+
return {
|
|
30
|
+
url: resolvedUrl, format: 'mocked', importAttributes: {
|
|
31
|
+
parentURL: context.parentURL,
|
|
32
|
+
}, shortCircuit: true
|
|
33
|
+
};
|
|
34
|
+
}
|
|
13
35
|
}
|
|
14
36
|
}
|
|
15
|
-
return
|
|
16
|
-
}, load(url, context,
|
|
17
|
-
if (
|
|
18
|
-
const
|
|
19
|
-
return {
|
|
20
|
-
shortCircuit: true, source: generateModule(encodedTargetURL), format: 'module',
|
|
21
|
-
};
|
|
37
|
+
return resolved;
|
|
38
|
+
}, load(url, context, nextLoader) {
|
|
39
|
+
if (context.format === 'mocked') {
|
|
40
|
+
const source = generateModule(context.importAttributes.parentURL, url);
|
|
41
|
+
return { source, format: 'module', shortCircuit: true };
|
|
22
42
|
}
|
|
23
|
-
return
|
|
43
|
+
return nextLoader(url, context);
|
|
24
44
|
}
|
|
25
45
|
});
|
|
26
|
-
|
|
27
|
-
|
|
46
|
+
export const mocksFor = new Map();
|
|
47
|
+
function generateModule(parent, url) {
|
|
28
48
|
const body = [
|
|
29
|
-
`import {
|
|
30
|
-
|
|
31
|
-
'let mapping = {__proto__: null};',
|
|
32
|
-
`const mock = mockedModules.get(${JSON.stringify(encodedTargetURL)});`,
|
|
49
|
+
`import {mocksFor} from ${JSON.stringify(import.meta.url)};`,
|
|
50
|
+
`const exports = mocksFor.get(${JSON.stringify(parent)});`,
|
|
33
51
|
];
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
for (var k in mapping) {
|
|
42
|
-
mapping[k] = mock.namespace[k];
|
|
43
|
-
}
|
|
44
|
-
});`);
|
|
45
|
-
return body.join('\n');
|
|
46
|
-
}
|
|
47
|
-
export const mockedModules = new Map();
|
|
48
|
-
function add(resolved, replacementProperties) {
|
|
49
|
-
const exportNames = Object.keys(replacementProperties);
|
|
50
|
-
const namespace = { __proto__: null };
|
|
51
|
-
const listeners = [];
|
|
52
|
-
for (const name of exportNames) {
|
|
53
|
-
let currentValueForPropertyName = replacementProperties[name];
|
|
54
|
-
Object.defineProperty(namespace, name, {
|
|
55
|
-
// @ts-ignore
|
|
56
|
-
__proto__: null,
|
|
57
|
-
enumerable: true,
|
|
58
|
-
get() {
|
|
59
|
-
return currentValueForPropertyName;
|
|
60
|
-
}, set(v) {
|
|
61
|
-
currentValueForPropertyName = v;
|
|
62
|
-
for (const fn of listeners) {
|
|
63
|
-
try {
|
|
64
|
-
fn(name);
|
|
65
|
-
}
|
|
66
|
-
catch (_a) {
|
|
67
|
-
/* noop */
|
|
68
|
-
}
|
|
52
|
+
if (parent) {
|
|
53
|
+
const mocksForParent = mocksFor.get(parent);
|
|
54
|
+
if (mocksForParent) {
|
|
55
|
+
const exports = mocksForParent.get(url);
|
|
56
|
+
if (exports) {
|
|
57
|
+
for (const key in exports) {
|
|
58
|
+
body.push(`export const ${key} = exports.get(${JSON.stringify(url)})[${JSON.stringify(key)}];`);
|
|
69
59
|
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
72
62
|
}
|
|
73
|
-
|
|
74
|
-
namespace, listeners,
|
|
75
|
-
});
|
|
76
|
-
mockedModuleExports.set(resolved, exportNames);
|
|
77
|
-
return namespace;
|
|
63
|
+
return body.join('\n');
|
|
78
64
|
}
|
|
79
|
-
|
|
80
|
-
|
|
65
|
+
let version = 0;
|
|
66
|
+
export function mock(modules = {}) {
|
|
81
67
|
return {
|
|
82
|
-
for(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
68
|
+
for(specifier_1) {
|
|
69
|
+
return __awaiter(this, arguments, void 0, function* (specifier, keep = false) {
|
|
70
|
+
try {
|
|
71
|
+
const scope = (version++).toString() + +new Date();
|
|
72
|
+
specifier = `${specifier}?${scope}`;
|
|
73
|
+
mocksFor.set(specifier, new Map(Object.entries(modules).map(([k, v]) => [`${k}?${scope}`, v])));
|
|
74
|
+
return yield import(specifier);
|
|
86
75
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
76
|
+
finally {
|
|
77
|
+
if (!keep)
|
|
78
|
+
mocksFor.delete(specifier);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
92
81
|
}
|
|
93
82
|
};
|
|
94
83
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-esm-mock",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Mock ES modules in Node.js using registerHooks",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -35,13 +35,15 @@
|
|
|
35
35
|
"typescript": "^5.5.3"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
+
"@types/chai": "^5.2.3",
|
|
38
39
|
"@types/node": "^25.9.3",
|
|
39
40
|
"@types/sinon": "^21.0.1",
|
|
41
|
+
"chai": "^6.2.2",
|
|
40
42
|
"sinon": "^22.0.0",
|
|
41
43
|
"ts-node": "^10.9.2"
|
|
42
44
|
},
|
|
43
45
|
"scripts": {
|
|
44
46
|
"build": "tsc",
|
|
45
|
-
"test": "node --
|
|
47
|
+
"test": "node --import ./utils/register.ts --no-warnings --test"
|
|
46
48
|
}
|
|
47
49
|
}
|