@marko/type-check 0.0.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/README.md +72 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +598 -0
- package/dist/run.d.ts +11 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Marko Type Check (@marko/type-check)
|
|
2
|
+
|
|
3
|
+
A CLI for running type checks on .marko, .ts, and .js files.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
npm install --save-dev @marko/type-check
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
Use the `marko-type-check` or `mtc` command followed by options to run type checks on your project files:
|
|
14
|
+
|
|
15
|
+
```terminal
|
|
16
|
+
marko-type-check [options]
|
|
17
|
+
|
|
18
|
+
# or with the shorthand
|
|
19
|
+
mtc [options]
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Options
|
|
23
|
+
|
|
24
|
+
| Option | Alias | Description | Default Value |
|
|
25
|
+
| ---------------- | ----- | ---------------------------------------------------------------------- | ---------------------------------- |
|
|
26
|
+
| --project <path> | -p | Path to the tsconfig or jsconfig file | ./tsconfig.json or ./jsconfig.json |
|
|
27
|
+
| --display <type> | -d | Set the display type for error output. Choices: codeframe or condensed | codeframe |
|
|
28
|
+
| --emit | -e | Emit .js, .d.ts, .marko (with types stripped), and .d.marko files | false |
|
|
29
|
+
| --help | -h | Display the help text | |
|
|
30
|
+
| --version | -v | Display the CLI version, Marko version, and TypeScript version | |
|
|
31
|
+
|
|
32
|
+
## Examples
|
|
33
|
+
|
|
34
|
+
### Run type check with the default tsconfig.json file:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
marko-type-check
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Run type check with a custom jsconfig.json file and condensed error output:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
mtc -p ./jsconfig.json -d condensed
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Run type check and emit output files:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
marko-type-check -e
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## FAQ
|
|
53
|
+
|
|
54
|
+
### What files are emitted with the `--emit` option?
|
|
55
|
+
|
|
56
|
+
The `emit` option outputs files similar to the [`tsc` cli](https://www.typescriptlang.org/docs/handbook/compiler-options.html). Meaning `.js` and `.d.ts` files will be output. Beyond that `.marko` files _with their types stripped_ and an associated `.d.marko` file will be output that serve a similar purpose to the `.js` and `.d.ts` files.
|
|
57
|
+
|
|
58
|
+
### What is a `.d.marko` file?
|
|
59
|
+
|
|
60
|
+
A `.d.marko` files is similar to a `.d.ts` file. All script content in the file will be processed as if the Marko script-lang was typescript and the Marko-VSCode plugin and this CLI will both prefer loading a `.d.marko` over an adjacent `.marko` file. The `.d.marko` files output by this tool will strip out any runtime code such that only type information is in the `.d.marko` output.
|
|
61
|
+
|
|
62
|
+
### Does this replace `tsc`?
|
|
63
|
+
|
|
64
|
+
Yes this replaces `tsc` since in order to provide proper type checking for `.marko` files the `.ts` and `.js` files must be processed as well.
|
|
65
|
+
|
|
66
|
+
## Contributing
|
|
67
|
+
|
|
68
|
+
Contributions are welcome! Please read our [Contributing Guidelines](CONTRIBUTING.md) for more information on how to contribute.
|
|
69
|
+
|
|
70
|
+
## License
|
|
71
|
+
|
|
72
|
+
This project is licensed under the [MIT License](LICENSE).
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
+
mod
|
|
24
|
+
));
|
|
25
|
+
|
|
26
|
+
// src/cli.ts
|
|
27
|
+
var import_fs = __toESM(require("fs"));
|
|
28
|
+
var import_path2 = __toESM(require("path"));
|
|
29
|
+
var import_module = require("module");
|
|
30
|
+
var import_arg = __toESM(require("arg"));
|
|
31
|
+
var import_kleur2 = __toESM(require("kleur"));
|
|
32
|
+
|
|
33
|
+
// src/run.ts
|
|
34
|
+
var import_path = __toESM(require("path"));
|
|
35
|
+
var import_tsserverlibrary = __toESM(require("typescript/lib/tsserverlibrary"));
|
|
36
|
+
var import_kleur = __toESM(require("kleur"));
|
|
37
|
+
var import_code_frame = require("@babel/code-frame");
|
|
38
|
+
var import_language_tools = require("@marko/language-tools");
|
|
39
|
+
var Display = {
|
|
40
|
+
codeframe: "codeframe",
|
|
41
|
+
condensed: "condensed"
|
|
42
|
+
};
|
|
43
|
+
var currentDirectory = import_tsserverlibrary.default.sys.getCurrentDirectory();
|
|
44
|
+
var fsPathReg = /^(?:[./\\]|[A-Z]:)/i;
|
|
45
|
+
var modulePartsReg = /^((?:@(?:[^/]+)\/)?(?:[^/]+))(.*)$/;
|
|
46
|
+
var extractCache = /* @__PURE__ */ new WeakMap();
|
|
47
|
+
var requiredTSCompilerOptions = {
|
|
48
|
+
module: import_tsserverlibrary.default.ModuleKind.ESNext,
|
|
49
|
+
moduleResolution: import_tsserverlibrary.default.ModuleResolutionKind.Bundler,
|
|
50
|
+
allowJs: true,
|
|
51
|
+
declaration: true,
|
|
52
|
+
skipLibCheck: true,
|
|
53
|
+
isolatedModules: true,
|
|
54
|
+
allowNonTsExtensions: true
|
|
55
|
+
};
|
|
56
|
+
var requiredTSCompilerOptionsEmit = {
|
|
57
|
+
...requiredTSCompilerOptions,
|
|
58
|
+
noEmit: false,
|
|
59
|
+
declaration: true,
|
|
60
|
+
emitDeclarationOnly: false
|
|
61
|
+
};
|
|
62
|
+
var requiredTSCompilerOptionsNoEmit = {
|
|
63
|
+
...requiredTSCompilerOptions,
|
|
64
|
+
noEmit: true,
|
|
65
|
+
declaration: false,
|
|
66
|
+
emitDeclarationOnly: false
|
|
67
|
+
};
|
|
68
|
+
var defaultTSConfig = {
|
|
69
|
+
include: [],
|
|
70
|
+
compilerOptions: {
|
|
71
|
+
lib: ["dom", "node", "esnext"]
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
function run(opts) {
|
|
75
|
+
var _a;
|
|
76
|
+
const {
|
|
77
|
+
emit = false,
|
|
78
|
+
display = Display.codeframe,
|
|
79
|
+
project: configFile = findConfigFile("tsconfig.json") || findConfigFile("jsconfig.json")
|
|
80
|
+
} = opts;
|
|
81
|
+
if (!configFile)
|
|
82
|
+
throw new Error("Could not find tsconfig.json or jsconfig.json");
|
|
83
|
+
const { host, parsedCommandLine, getProcessor } = createCompilerHost(
|
|
84
|
+
configFile,
|
|
85
|
+
emit ? requiredTSCompilerOptionsEmit : requiredTSCompilerOptionsNoEmit
|
|
86
|
+
);
|
|
87
|
+
const formatSettings = import_tsserverlibrary.default.getDefaultFormatCodeSettings(
|
|
88
|
+
((_a = host.getNewLine) == null ? void 0 : _a.call(host)) || import_tsserverlibrary.default.sys.newLine
|
|
89
|
+
);
|
|
90
|
+
const report = {
|
|
91
|
+
out: [],
|
|
92
|
+
display,
|
|
93
|
+
hasErrors: false,
|
|
94
|
+
formatSettings
|
|
95
|
+
};
|
|
96
|
+
const program = import_tsserverlibrary.default.createProgram({
|
|
97
|
+
host,
|
|
98
|
+
options: parsedCommandLine.options,
|
|
99
|
+
rootNames: parsedCommandLine.fileNames,
|
|
100
|
+
projectReferences: parsedCommandLine.projectReferences
|
|
101
|
+
});
|
|
102
|
+
reportDiagnostics(report, import_tsserverlibrary.default.getPreEmitDiagnostics(program));
|
|
103
|
+
if (!report.hasErrors) {
|
|
104
|
+
const typeChecker = program.getTypeChecker();
|
|
105
|
+
const printer = import_tsserverlibrary.default.createPrinter({
|
|
106
|
+
noEmitHelpers: true,
|
|
107
|
+
removeComments: true
|
|
108
|
+
});
|
|
109
|
+
const emitResult = program.emit(
|
|
110
|
+
void 0,
|
|
111
|
+
emit ? (fileName, _text, writeByteOrderMark, onError, sourceFiles, data) => {
|
|
112
|
+
const processor = (sourceFiles == null ? void 0 : sourceFiles.length) === 1 && getProcessor(sourceFiles[0].fileName) || void 0;
|
|
113
|
+
if (processor) {
|
|
114
|
+
const [sourceFile] = sourceFiles;
|
|
115
|
+
const processorExt = (0, import_language_tools.getExt)(sourceFile.fileName);
|
|
116
|
+
const inDtsExt = processorExt + import_tsserverlibrary.default.Extension.Dts;
|
|
117
|
+
const inJsExt = processorExt + import_tsserverlibrary.default.Extension.Js;
|
|
118
|
+
const inExt = fileName.endsWith(inDtsExt) ? inDtsExt : fileName.endsWith(inJsExt) ? inJsExt : void 0;
|
|
119
|
+
if (!inExt) {
|
|
120
|
+
throw new Error("Unexpected file extension: " + fileName);
|
|
121
|
+
}
|
|
122
|
+
const isDts = inExt === inDtsExt;
|
|
123
|
+
let outFileName = fileName;
|
|
124
|
+
if ((0, import_language_tools.isDefinitionFile)(sourceFile.fileName)) {
|
|
125
|
+
if (!isDts)
|
|
126
|
+
return;
|
|
127
|
+
outFileName = fileName.slice(0, -inExt.length) + processorExt;
|
|
128
|
+
} else {
|
|
129
|
+
if (isDts && program.getSourceFile(
|
|
130
|
+
`${sourceFile.fileName.slice(
|
|
131
|
+
0,
|
|
132
|
+
-processorExt.length
|
|
133
|
+
)}.d${processorExt}`
|
|
134
|
+
)) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
outFileName = fileName.slice(0, -inExt.length) + (isDts ? ".d" : "") + processorExt;
|
|
138
|
+
}
|
|
139
|
+
const extracted = extractCache.get(
|
|
140
|
+
program.getSourceFile(sourceFile.fileName)
|
|
141
|
+
);
|
|
142
|
+
const printContext = {
|
|
143
|
+
extracted,
|
|
144
|
+
printer,
|
|
145
|
+
typeChecker,
|
|
146
|
+
sourceFile,
|
|
147
|
+
formatSettings
|
|
148
|
+
};
|
|
149
|
+
host.writeFile(
|
|
150
|
+
outFileName,
|
|
151
|
+
isDts ? processor.printTypes(printContext).code : processor.print(printContext).code,
|
|
152
|
+
writeByteOrderMark,
|
|
153
|
+
onError,
|
|
154
|
+
sourceFiles,
|
|
155
|
+
data
|
|
156
|
+
);
|
|
157
|
+
} else {
|
|
158
|
+
host.writeFile(
|
|
159
|
+
fileName,
|
|
160
|
+
_text,
|
|
161
|
+
writeByteOrderMark,
|
|
162
|
+
onError,
|
|
163
|
+
sourceFiles,
|
|
164
|
+
data
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
} : void 0,
|
|
168
|
+
void 0,
|
|
169
|
+
false
|
|
170
|
+
);
|
|
171
|
+
reportDiagnostics(report, emitResult.diagnostics);
|
|
172
|
+
}
|
|
173
|
+
const lineSep = report.formatSettings.newLineCharacter + report.formatSettings.newLineCharacter;
|
|
174
|
+
console.log(report.out.join(lineSep));
|
|
175
|
+
process.exitCode = report.hasErrors ? 1 : 0;
|
|
176
|
+
}
|
|
177
|
+
function createCompilerHost(configFile, compilerOptions) {
|
|
178
|
+
const getProcessor = (fileName) => {
|
|
179
|
+
const ext = (0, import_language_tools.getExt)(fileName);
|
|
180
|
+
return ext ? processors[ext] : void 0;
|
|
181
|
+
};
|
|
182
|
+
const resolveModuleNameLiterals = (moduleLiterals, containingFile, redirectedReference, options, _containingSourceFile, _reusedNames) => {
|
|
183
|
+
return moduleLiterals.map((moduleLiteral) => {
|
|
184
|
+
return import_tsserverlibrary.default.bundlerModuleNameResolver(
|
|
185
|
+
moduleLiteral.text,
|
|
186
|
+
containingFile,
|
|
187
|
+
options,
|
|
188
|
+
host,
|
|
189
|
+
resolutionCache,
|
|
190
|
+
redirectedReference
|
|
191
|
+
);
|
|
192
|
+
});
|
|
193
|
+
};
|
|
194
|
+
const parsedCommandLine = import_tsserverlibrary.default.parseJsonConfigFileContent(
|
|
195
|
+
configFile && import_tsserverlibrary.default.readConfigFile(configFile, import_tsserverlibrary.default.sys.readFile).config || defaultTSConfig,
|
|
196
|
+
import_tsserverlibrary.default.sys,
|
|
197
|
+
currentDirectory,
|
|
198
|
+
compilerOptions,
|
|
199
|
+
configFile,
|
|
200
|
+
void 0,
|
|
201
|
+
import_language_tools.Processors.extensions.map((extension) => ({
|
|
202
|
+
extension,
|
|
203
|
+
isMixedContent: false,
|
|
204
|
+
scriptKind: import_tsserverlibrary.default.ScriptKind.Deferred
|
|
205
|
+
}))
|
|
206
|
+
);
|
|
207
|
+
const host = {
|
|
208
|
+
getDefaultLibFileName: import_tsserverlibrary.default.getDefaultLibFilePath,
|
|
209
|
+
writeFile: import_tsserverlibrary.default.sys.writeFile,
|
|
210
|
+
getCurrentDirectory: import_tsserverlibrary.default.sys.getCurrentDirectory,
|
|
211
|
+
getDirectories: import_tsserverlibrary.default.sys.getDirectories,
|
|
212
|
+
getCanonicalFileName: (fileName) => import_tsserverlibrary.default.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(),
|
|
213
|
+
getNewLine: () => import_tsserverlibrary.default.sys.newLine,
|
|
214
|
+
useCaseSensitiveFileNames: () => import_tsserverlibrary.default.sys.useCaseSensitiveFileNames,
|
|
215
|
+
fileExists: import_tsserverlibrary.default.sys.fileExists,
|
|
216
|
+
readFile: import_tsserverlibrary.default.sys.readFile,
|
|
217
|
+
readDirectory: (path3, extensions, exclude, include, depth) => import_tsserverlibrary.default.sys.readDirectory(
|
|
218
|
+
path3,
|
|
219
|
+
extensions == null ? void 0 : extensions.concat(import_language_tools.Processors.extensions),
|
|
220
|
+
exclude,
|
|
221
|
+
include,
|
|
222
|
+
depth
|
|
223
|
+
),
|
|
224
|
+
resolveModuleNameLiterals(moduleLiterals, containingFile, redirectedReference, options, containingSourceFile, reusedNames) {
|
|
225
|
+
let normalModuleLiterals = moduleLiterals;
|
|
226
|
+
let resolvedModules;
|
|
227
|
+
for (let i = 0; i < moduleLiterals.length; i++) {
|
|
228
|
+
const moduleName = moduleLiterals[i].text;
|
|
229
|
+
const process2 = moduleName[0] !== "*" ? getProcessor(moduleName) : void 0;
|
|
230
|
+
if (process2) {
|
|
231
|
+
let resolvedFileName;
|
|
232
|
+
if (fsPathReg.test(moduleName)) {
|
|
233
|
+
resolvedFileName = import_path.default.resolve(containingFile, "..", moduleName);
|
|
234
|
+
} else {
|
|
235
|
+
const [, nodeModuleName, relativeModulePath] = modulePartsReg.exec(moduleName);
|
|
236
|
+
const { resolvedModule } = import_tsserverlibrary.default.resolveModuleName(
|
|
237
|
+
`${nodeModuleName}/package.json`,
|
|
238
|
+
containingFile,
|
|
239
|
+
options,
|
|
240
|
+
host,
|
|
241
|
+
resolutionCache
|
|
242
|
+
);
|
|
243
|
+
if (resolvedModule) {
|
|
244
|
+
resolvedFileName = import_path.default.join(
|
|
245
|
+
resolvedModule.resolvedFileName,
|
|
246
|
+
"..",
|
|
247
|
+
relativeModulePath
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (!resolvedModules) {
|
|
252
|
+
resolvedModules = [];
|
|
253
|
+
normalModuleLiterals = [];
|
|
254
|
+
for (let j = 0; j < i; j++) {
|
|
255
|
+
resolvedModules.push(void 0);
|
|
256
|
+
normalModuleLiterals.push(moduleLiterals[j]);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (resolvedFileName) {
|
|
260
|
+
if ((0, import_language_tools.isDefinitionFile)(resolvedFileName)) {
|
|
261
|
+
if (!host.fileExists(resolvedFileName)) {
|
|
262
|
+
resolvedFileName = void 0;
|
|
263
|
+
}
|
|
264
|
+
} else {
|
|
265
|
+
const ext = (0, import_language_tools.getExt)(resolvedFileName);
|
|
266
|
+
const definitionFile = `${resolvedFileName.slice(
|
|
267
|
+
0,
|
|
268
|
+
-ext.length
|
|
269
|
+
)}.d${ext}`;
|
|
270
|
+
if (host.fileExists(definitionFile)) {
|
|
271
|
+
resolvedFileName = definitionFile;
|
|
272
|
+
} else if (!host.fileExists(resolvedFileName)) {
|
|
273
|
+
resolvedFileName = void 0;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
resolvedModules.push({
|
|
278
|
+
resolvedModule: resolvedFileName ? {
|
|
279
|
+
resolvedFileName,
|
|
280
|
+
extension: process2.getScriptExtension(resolvedFileName),
|
|
281
|
+
isExternalLibraryImport: false
|
|
282
|
+
} : void 0
|
|
283
|
+
});
|
|
284
|
+
} else if (resolvedModules) {
|
|
285
|
+
resolvedModules.push(void 0);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
const normalResolvedModules = normalModuleLiterals.length ? resolveModuleNameLiterals(
|
|
289
|
+
normalModuleLiterals,
|
|
290
|
+
containingFile,
|
|
291
|
+
redirectedReference,
|
|
292
|
+
options,
|
|
293
|
+
containingSourceFile,
|
|
294
|
+
reusedNames
|
|
295
|
+
) : void 0;
|
|
296
|
+
if (resolvedModules) {
|
|
297
|
+
if (normalResolvedModules) {
|
|
298
|
+
for (let i = 0, j = 0; i < resolvedModules.length; i++) {
|
|
299
|
+
if (!resolvedModules[i]) {
|
|
300
|
+
resolvedModules[i] = normalResolvedModules[j++];
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return resolvedModules;
|
|
305
|
+
} else {
|
|
306
|
+
return normalResolvedModules;
|
|
307
|
+
}
|
|
308
|
+
},
|
|
309
|
+
getSourceFile: (fileName, languageVersion) => {
|
|
310
|
+
const processor = getProcessor(fileName);
|
|
311
|
+
const code = host.readFile(fileName);
|
|
312
|
+
if (code !== void 0) {
|
|
313
|
+
if (processor) {
|
|
314
|
+
const extracted = processor.extract(fileName, code);
|
|
315
|
+
const sourceFile = import_tsserverlibrary.default.createSourceFile(
|
|
316
|
+
fileName,
|
|
317
|
+
extracted.toString(),
|
|
318
|
+
languageVersion,
|
|
319
|
+
true,
|
|
320
|
+
processor.getScriptKind(fileName)
|
|
321
|
+
);
|
|
322
|
+
extractCache.set(sourceFile, extracted);
|
|
323
|
+
return sourceFile;
|
|
324
|
+
}
|
|
325
|
+
return import_tsserverlibrary.default.createSourceFile(fileName, code, languageVersion, true);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
const resolutionCache = import_tsserverlibrary.default.createModuleResolutionCache(
|
|
330
|
+
currentDirectory,
|
|
331
|
+
host.getCanonicalFileName,
|
|
332
|
+
parsedCommandLine.options
|
|
333
|
+
);
|
|
334
|
+
const processors = import_language_tools.Processors.create({
|
|
335
|
+
ts: import_tsserverlibrary.default,
|
|
336
|
+
host,
|
|
337
|
+
configFile
|
|
338
|
+
});
|
|
339
|
+
parsedCommandLine.fileNames = [
|
|
340
|
+
...new Set(
|
|
341
|
+
parsedCommandLine.fileNames.concat(
|
|
342
|
+
Object.values(processors).map((processor) => {
|
|
343
|
+
var _a;
|
|
344
|
+
return (_a = processor.getRootNames) == null ? void 0 : _a.call(processor);
|
|
345
|
+
}).flat().filter(Boolean)
|
|
346
|
+
)
|
|
347
|
+
)
|
|
348
|
+
];
|
|
349
|
+
return {
|
|
350
|
+
host,
|
|
351
|
+
parsedCommandLine,
|
|
352
|
+
getProcessor
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
function reportDiagnostics(report, diags) {
|
|
356
|
+
for (const diag of diags) {
|
|
357
|
+
if (diag.file && diag.start !== void 0) {
|
|
358
|
+
const extracted = extractCache.get(diag.file);
|
|
359
|
+
let code = diag.file.text;
|
|
360
|
+
let loc;
|
|
361
|
+
if (extracted) {
|
|
362
|
+
loc = extracted.sourceLocationAt(
|
|
363
|
+
diag.start,
|
|
364
|
+
diag.start + (diag.length || 0)
|
|
365
|
+
);
|
|
366
|
+
code = extracted.parsed.code;
|
|
367
|
+
if (!loc)
|
|
368
|
+
continue;
|
|
369
|
+
} else {
|
|
370
|
+
const start = import_tsserverlibrary.default.getLineAndCharacterOfPosition(diag.file, diag.start);
|
|
371
|
+
const end = diag.length ? import_tsserverlibrary.default.getLineAndCharacterOfPosition(
|
|
372
|
+
diag.file,
|
|
373
|
+
diag.start + diag.length
|
|
374
|
+
) : start;
|
|
375
|
+
loc = {
|
|
376
|
+
start,
|
|
377
|
+
end
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
if (diag.category === import_tsserverlibrary.default.DiagnosticCategory.Error) {
|
|
381
|
+
report.hasErrors = true;
|
|
382
|
+
}
|
|
383
|
+
const diagMessage = flattenDiagnosticMessage(
|
|
384
|
+
diag.messageText,
|
|
385
|
+
report.display,
|
|
386
|
+
report.formatSettings.newLineCharacter
|
|
387
|
+
);
|
|
388
|
+
report.out.push(
|
|
389
|
+
`${import_kleur.default.cyan(
|
|
390
|
+
import_path.default.relative(currentDirectory, diag.file.fileName)
|
|
391
|
+
)}:${import_kleur.default.yellow(loc.start.line + 1)}:${import_kleur.default.yellow(
|
|
392
|
+
loc.start.character + 1
|
|
393
|
+
)} - ${coloredDiagnosticCategory(diag.category)} ${import_kleur.default.dim(
|
|
394
|
+
`TS${diag.code}`
|
|
395
|
+
)}${report.formatSettings.newLineCharacter}${report.display === Display.codeframe ? report.formatSettings.newLineCharacter + formatCodeFrameMessage(code, loc, diagMessage) : diagMessage}`
|
|
396
|
+
);
|
|
397
|
+
} else {
|
|
398
|
+
if (diag.category === import_tsserverlibrary.default.DiagnosticCategory.Error) {
|
|
399
|
+
report.hasErrors = true;
|
|
400
|
+
}
|
|
401
|
+
report.out.push(
|
|
402
|
+
flattenDiagnosticMessage(
|
|
403
|
+
diag.messageText,
|
|
404
|
+
report.display,
|
|
405
|
+
report.formatSettings.newLineCharacter
|
|
406
|
+
)
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
if (diag.relatedInformation && report.display === Display.codeframe) {
|
|
410
|
+
reportRelatedDiagnostics(report, diag.relatedInformation);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
function reportRelatedDiagnostics(report, diags) {
|
|
415
|
+
for (const diag of diags) {
|
|
416
|
+
if (diag.file && diag.start) {
|
|
417
|
+
const extracted = extractCache.get(diag.file);
|
|
418
|
+
let code = diag.file.text;
|
|
419
|
+
let loc;
|
|
420
|
+
if (extracted) {
|
|
421
|
+
loc = extracted.sourceLocationAt(
|
|
422
|
+
diag.start,
|
|
423
|
+
diag.start + (diag.length || 0)
|
|
424
|
+
);
|
|
425
|
+
code = extracted.parsed.code;
|
|
426
|
+
} else {
|
|
427
|
+
const start = import_tsserverlibrary.default.getLineAndCharacterOfPosition(diag.file, diag.start);
|
|
428
|
+
const end = diag.length ? import_tsserverlibrary.default.getLineAndCharacterOfPosition(
|
|
429
|
+
diag.file,
|
|
430
|
+
diag.start + diag.length
|
|
431
|
+
) : start;
|
|
432
|
+
loc = {
|
|
433
|
+
start,
|
|
434
|
+
end
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
if (loc) {
|
|
438
|
+
report.out.push(
|
|
439
|
+
formatCodeFrameMessage(
|
|
440
|
+
code,
|
|
441
|
+
loc,
|
|
442
|
+
`${flattenDiagnosticMessage(
|
|
443
|
+
diag.messageText,
|
|
444
|
+
report.display,
|
|
445
|
+
report.formatSettings.newLineCharacter
|
|
446
|
+
)} @ ${import_path.default.relative(currentDirectory, diag.file.fileName)}:${loc.start.line + 1}:${loc.start.character + 1}`
|
|
447
|
+
)
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
} else {
|
|
451
|
+
report.out.push(
|
|
452
|
+
flattenDiagnosticMessage(
|
|
453
|
+
diag.messageText,
|
|
454
|
+
report.display,
|
|
455
|
+
report.formatSettings.newLineCharacter
|
|
456
|
+
)
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
function formatCodeFrameMessage(code, loc, message) {
|
|
462
|
+
return (0, import_code_frame.codeFrameColumns)(
|
|
463
|
+
code,
|
|
464
|
+
{
|
|
465
|
+
start: {
|
|
466
|
+
line: loc.start.line + 1,
|
|
467
|
+
column: loc.start.character + 1
|
|
468
|
+
},
|
|
469
|
+
end: {
|
|
470
|
+
line: loc.end.line + 1,
|
|
471
|
+
column: loc.end.character + 1
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
highlightCode: true,
|
|
476
|
+
message
|
|
477
|
+
}
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
function flattenDiagnosticMessage(message, display, newLine) {
|
|
481
|
+
const str = import_tsserverlibrary.default.flattenDiagnosticMessageText(message, newLine);
|
|
482
|
+
const strWithNewlines = str.replace(/(?:\r?\n)[ \t]+/g, newLine);
|
|
483
|
+
return str === strWithNewlines ? str : (display === Display.codeframe ? newLine : "") + strWithNewlines;
|
|
484
|
+
}
|
|
485
|
+
function coloredDiagnosticCategory(category) {
|
|
486
|
+
switch (category) {
|
|
487
|
+
case import_tsserverlibrary.default.DiagnosticCategory.Error:
|
|
488
|
+
return import_kleur.default.red("error");
|
|
489
|
+
case import_tsserverlibrary.default.DiagnosticCategory.Warning:
|
|
490
|
+
return import_kleur.default.yellow("warning");
|
|
491
|
+
case import_tsserverlibrary.default.DiagnosticCategory.Message:
|
|
492
|
+
return import_kleur.default.blue("message");
|
|
493
|
+
case import_tsserverlibrary.default.DiagnosticCategory.Suggestion:
|
|
494
|
+
return import_kleur.default.magenta("suggestion");
|
|
495
|
+
default:
|
|
496
|
+
return import_kleur.default.red(
|
|
497
|
+
(import_tsserverlibrary.default.DiagnosticCategory[category] || "unknown").toLocaleLowerCase()
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
function findConfigFile(name) {
|
|
502
|
+
return import_tsserverlibrary.default.findConfigFile(currentDirectory, import_tsserverlibrary.default.sys.fileExists, name);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// src/cli.ts
|
|
506
|
+
var args = (0, import_arg.default)(
|
|
507
|
+
{
|
|
508
|
+
"--project": String,
|
|
509
|
+
"--display": String,
|
|
510
|
+
"--emit": Boolean,
|
|
511
|
+
"--help": Boolean,
|
|
512
|
+
"--version": Boolean,
|
|
513
|
+
"-p": "--project",
|
|
514
|
+
"-d": "--display",
|
|
515
|
+
"-e": "--emit",
|
|
516
|
+
"-h": "--help",
|
|
517
|
+
"-v": "--version"
|
|
518
|
+
},
|
|
519
|
+
{ permissive: false, argv: process.argv.slice(2) }
|
|
520
|
+
);
|
|
521
|
+
if (args["--help"]) {
|
|
522
|
+
console.log(`${import_kleur2.default.bold(
|
|
523
|
+
`Usage: ${import_kleur2.default.cyan("marko-type-check")} ${import_kleur2.default.magenta(
|
|
524
|
+
`[options]`
|
|
525
|
+
)} | ${import_kleur2.default.cyan("mtc")} ${import_kleur2.default.magenta(`[options]`)}
|
|
526
|
+
`
|
|
527
|
+
)}
|
|
528
|
+
A command-line interface for running type checks on .marko, .ts, and .js files.
|
|
529
|
+
|
|
530
|
+
${import_kleur2.default.bold("Options:")}
|
|
531
|
+
${import_kleur2.default.yellow("-p, --project")} ${import_kleur2.default.magenta(
|
|
532
|
+
"<path>"
|
|
533
|
+
)} Path to the tsconfig or jsconfig file (default: ${import_kleur2.default.green(
|
|
534
|
+
`"./tsconfig.json"`
|
|
535
|
+
)} or ${import_kleur2.default.green(`"./jsconfig.json"`)})
|
|
536
|
+
${import_kleur2.default.yellow("-d, --display")} ${import_kleur2.default.magenta(
|
|
537
|
+
"<type>"
|
|
538
|
+
)} Set the display type for error output. Choices: ${import_kleur2.default.green(
|
|
539
|
+
`"codeframe"`
|
|
540
|
+
)} or ${import_kleur2.default.green(`"condensed"`)} (default: ${import_kleur2.default.green(`"codeframe"`)})
|
|
541
|
+
${import_kleur2.default.yellow(
|
|
542
|
+
"-e, --emit"
|
|
543
|
+
)} Emit .js, .d.ts, .marko (with types stripped), and .d.marko files (default: ${import_kleur2.default.magenta(
|
|
544
|
+
"false"
|
|
545
|
+
)})
|
|
546
|
+
${import_kleur2.default.yellow(
|
|
547
|
+
"-v, --version"
|
|
548
|
+
)} Display the CLI version, Marko version, and TypeScript version
|
|
549
|
+
${import_kleur2.default.yellow("-h, --help")} Display this help text
|
|
550
|
+
|
|
551
|
+
${import_kleur2.default.bold("Examples:")}
|
|
552
|
+
${import_kleur2.default.cyan("marko-type-check")} --project ./tsconfig.json
|
|
553
|
+
${import_kleur2.default.cyan("mtc")} -p ./jsconfig.json -d condensed -e
|
|
554
|
+
|
|
555
|
+
For more information, visit ${import_kleur2.default.blue(
|
|
556
|
+
"https://github.com/marko-js/language-server/tree/main/packages/marko-type-check"
|
|
557
|
+
)}
|
|
558
|
+
`);
|
|
559
|
+
} else if (args["--version"]) {
|
|
560
|
+
const require2 = (0, import_module.createRequire)(__dirname);
|
|
561
|
+
const getPackageVersion = (id) => {
|
|
562
|
+
try {
|
|
563
|
+
return `${id} v${require2(`${id}/package.json`).version}`;
|
|
564
|
+
} catch {
|
|
565
|
+
return `${id} unknown version`;
|
|
566
|
+
}
|
|
567
|
+
};
|
|
568
|
+
console.log(
|
|
569
|
+
`marko-type-check v${require2("../package.json").version} (${[
|
|
570
|
+
getPackageVersion("marko"),
|
|
571
|
+
getPackageVersion("@marko/compiler"),
|
|
572
|
+
getPackageVersion("typescript")
|
|
573
|
+
].join(", ")})`
|
|
574
|
+
);
|
|
575
|
+
} else {
|
|
576
|
+
const {
|
|
577
|
+
"--emit": emit,
|
|
578
|
+
"--display": display = process.env.CI ? Display.condensed : Display.codeframe
|
|
579
|
+
} = args;
|
|
580
|
+
let { "--project": project } = args;
|
|
581
|
+
if (project) {
|
|
582
|
+
project = import_path2.default.resolve(process.cwd(), project);
|
|
583
|
+
if (!import_fs.default.existsSync(project)) {
|
|
584
|
+
throw new Error(`Project path does not exist: ${project}`);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
checkDisplay(display);
|
|
588
|
+
run({ project, display, emit });
|
|
589
|
+
}
|
|
590
|
+
function checkDisplay(display) {
|
|
591
|
+
if (display && Display[display] === void 0) {
|
|
592
|
+
throw new Error(
|
|
593
|
+
`Invalid display option, must be one of: ${Object.values(Display).join(
|
|
594
|
+
", "
|
|
595
|
+
)}`
|
|
596
|
+
);
|
|
597
|
+
}
|
|
598
|
+
}
|
package/dist/run.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const Display: {
|
|
2
|
+
readonly codeframe: "codeframe";
|
|
3
|
+
readonly condensed: "condensed";
|
|
4
|
+
};
|
|
5
|
+
export type Display = (typeof Display)[keyof typeof Display];
|
|
6
|
+
export interface Options {
|
|
7
|
+
project?: string;
|
|
8
|
+
display?: Display;
|
|
9
|
+
emit?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export default function run(opts: Options): void;
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@marko/type-check",
|
|
3
|
+
"description": "A CLI to type check Marko projects",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"bugs": "https://github.com/marko-js/language-server/issues/new?template=Bug_report.md",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"@babel/code-frame": "^7.18.6",
|
|
8
|
+
"@marko/language-tools": "^2.0.0",
|
|
9
|
+
"arg": "^5.0.2",
|
|
10
|
+
"kleur": "^4.1.5",
|
|
11
|
+
"strip-json-comments": "^5.0.0",
|
|
12
|
+
"typescript": "5.0.2"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/babel__code-frame": "^7.0.3"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"!**/__tests__",
|
|
20
|
+
"!**/*.tsbuildinfo"
|
|
21
|
+
],
|
|
22
|
+
"homepage": "https://github.com/marko-js/language-server/tree/main/packages/type-check/README.md",
|
|
23
|
+
"keywords": [
|
|
24
|
+
"type-check",
|
|
25
|
+
"marko",
|
|
26
|
+
"tsc",
|
|
27
|
+
"typescript",
|
|
28
|
+
"tools"
|
|
29
|
+
],
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"bin": {
|
|
32
|
+
"marko-type-check": "dist/cli.js",
|
|
33
|
+
"mtc": "dist/cli.js"
|
|
34
|
+
},
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "https://github.com/marko-js/language-server/tree/main/packages/type-check"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsc -b && tsx build.mts"
|
|
41
|
+
}
|
|
42
|
+
}
|