@athree/module-loader 2.0.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/package.json +12 -0
- package/src/main/index.ts +1 -0
- package/src/main/module-loader.ts +50 -0
- package/src/main/register.ts +3 -0
- package/tsconfig.json +8 -0
package/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './module-loader.js';
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { readFile, stat } from 'node:fs/promises';
|
|
2
|
+
import { LoadFnOutput, LoadHookContext, ResolveFnOutput, ResolveHookContext } from 'node:module';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
type ResolveNext = (specifier: string, context: ResolveHookContext) => Promise<ResolveFnOutput>;
|
|
6
|
+
type LoadNext = (specifier: string, context: LoadHookContext) => Promise<LoadFnOutput>;
|
|
7
|
+
|
|
8
|
+
export async function resolve(specifier: string, context: ResolveHookContext, nextResolve: ResolveNext): Promise<ResolveFnOutput> {
|
|
9
|
+
// Allow specifying ?t=timestamp directly in await import()
|
|
10
|
+
// to force cache busting
|
|
11
|
+
let ts = 0;
|
|
12
|
+
if (specifier.includes('?t=')) {
|
|
13
|
+
const [_spec, _ts] = specifier.split('?t=');
|
|
14
|
+
specifier = _spec;
|
|
15
|
+
ts = Number(_ts) || 0;
|
|
16
|
+
}
|
|
17
|
+
// Resolve the module as usual,
|
|
18
|
+
// this results either in file:// or custom specifiers like `node:`
|
|
19
|
+
const resolved = await nextResolve(specifier, context);
|
|
20
|
+
if (!resolved.url.startsWith('file://')) {
|
|
21
|
+
return resolved;
|
|
22
|
+
}
|
|
23
|
+
// For file modules, if ts is provided explicitly in resolve request,
|
|
24
|
+
// then use that, otherwise use the file's mtime
|
|
25
|
+
const file = fileURLToPath(resolved.url);
|
|
26
|
+
if (ts > 0) {
|
|
27
|
+
return {
|
|
28
|
+
format: resolved.format,
|
|
29
|
+
url: resolved.url + `?t=${ts}`,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
const { mtime } = await stat(file);
|
|
33
|
+
return {
|
|
34
|
+
format: resolved.format,
|
|
35
|
+
url: resolved.url + `?t=${mtime.getTime()}`,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function load(specifier: string, context: LoadHookContext, nextLoad: LoadNext): Promise<LoadFnOutput> {
|
|
40
|
+
if (/\.md($|\?)/.test(specifier)) {
|
|
41
|
+
const file = fileURLToPath(specifier);
|
|
42
|
+
const source = await readFile(file, 'utf-8');
|
|
43
|
+
return {
|
|
44
|
+
format: 'module',
|
|
45
|
+
shortCircuit: true,
|
|
46
|
+
source: `export default ${JSON.stringify(source)}`,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return nextLoad(specifier, context);
|
|
50
|
+
}
|