-
-
Notifications
You must be signed in to change notification settings - Fork 135
/
loaders.ts
127 lines (116 loc) · 3.83 KB
/
loaders.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/* eslint-disable @typescript-eslint/no-require-imports */
import { existsSync, rmSync, writeFileSync } from 'fs';
import { rm, writeFile } from 'fs/promises';
import path from 'path';
import { pathToFileURL } from 'url';
import { Loader, LoaderSync } from './types.js';
let importFresh: typeof import('import-fresh');
export const loadJsSync: LoaderSync = function loadJsSync(filepath) {
if (importFresh === undefined) {
importFresh = require('import-fresh');
}
return importFresh(filepath);
};
export const loadJs: Loader = async function loadJs(filepath) {
try {
const { href } = pathToFileURL(filepath);
return (await import(href)).default;
} catch (error) {
return loadJsSync(filepath, '');
}
};
let parseJson: typeof import('parse-json');
export const loadJson: LoaderSync = function loadJson(filepath, content) {
if (parseJson === undefined) {
parseJson = require('parse-json');
}
try {
return parseJson(content);
} catch (error) {
error.message = `JSON Error in ${filepath}:\n${error.message}`;
throw error;
}
};
let yaml: typeof import('js-yaml');
export const loadYaml: LoaderSync = function loadYaml(filepath, content) {
if (yaml === undefined) {
yaml = require('js-yaml');
}
try {
return yaml.load(content);
} catch (error) {
error.message = `YAML Error in ${filepath}:\n${error.message}`;
throw error;
}
};
let typescript: typeof import('typescript');
export const loadTsSync: LoaderSync = function loadTsSync(filepath, content) {
/* istanbul ignore next -- @preserve */
if (typescript === undefined) {
typescript = require('typescript');
}
const compiledFilepath = `${filepath.slice(0, -2)}cjs`;
try {
const config = resolveTsConfig(path.dirname(filepath)) ?? {};
config.compilerOptions = {
...config.compilerOptions,
module: typescript.ModuleKind.NodeNext,
moduleResolution: typescript.ModuleResolutionKind.NodeNext,
target: typescript.ScriptTarget.ES2022,
noEmit: false,
};
content = typescript.transpileModule(content, config).outputText;
writeFileSync(compiledFilepath, content);
return loadJsSync(compiledFilepath, content).default;
} catch (error) {
error.message = `TypeScript Error in ${filepath}:\n${error.message}`;
throw error;
} finally {
if (existsSync(compiledFilepath)) {
rmSync(compiledFilepath);
}
}
};
export const loadTs: Loader = async function loadTs(filepath, content) {
if (typescript === undefined) {
typescript = (await import('typescript')).default;
}
const compiledFilepath = `${filepath.slice(0, -2)}mjs`;
try {
const config = resolveTsConfig(path.dirname(filepath)) ?? {};
config.compilerOptions = {
...config.compilerOptions,
module: typescript.ModuleKind.ES2022,
moduleResolution: typescript.ModuleResolutionKind.Bundler,
target: typescript.ScriptTarget.ES2022,
noEmit: false,
};
content = typescript.transpileModule(content, config).outputText;
await writeFile(compiledFilepath, content);
const { href } = pathToFileURL(compiledFilepath);
return (await import(href)).default;
} catch (error) {
error.message = `TypeScript Error in ${filepath}:\n${error.message}`;
throw error;
} finally {
if (existsSync(compiledFilepath)) {
await rm(compiledFilepath);
}
}
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function resolveTsConfig(directory: string): any {
const filePath = typescript.findConfigFile(directory, (fileName) => {
return typescript.sys.fileExists(fileName);
});
if (filePath !== undefined) {
const { config, error } = typescript.readConfigFile(filePath, (path) =>
typescript.sys.readFile(path),
);
if (error) {
throw new Error(`Error in ${filePath}: ${error.messageText.toString()}`);
}
return config;
}
return;
}