@torpor/check 1.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/README.md ADDED
@@ -0,0 +1,23 @@
1
+ # torpor/check
2
+
3
+ A command line tool that checks Torpor files for errors.
4
+
5
+ ## Features
6
+
7
+ - checks for build errors (e.g. unclosed tags)
8
+ - checks for script and type errors
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ npm install --save-dev @torpor/check
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ```
19
+ torp-check [path]
20
+ ```
21
+
22
+ Checks all Torpor files in the given folder (or a single file), and prints any
23
+ errors found. If no path is given, the current folder is checked.
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,43 @@
1
+ #! /usr/bin/env node
2
+ import { n as check, t as check$1 } from "../checkFile-BvvjrnaS.mjs";
3
+ import chalk from "chalk";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ //#region src/printErrors.ts
7
+ function printErrors(folder, errors) {
8
+ errors.sort((a, b) => a.path.localeCompare(b.path));
9
+ for (let error of errors) {
10
+ console.log(`${chalk.green(path.relative(folder, error.path))}:${chalk.yellow(error.range.start.line)}:${chalk.yellow(error.range.start.character)} - ${chalk.red("error")}${error.code ? chalk.gray(` TS${error.code}`) : ""}: ${error.message}`);
11
+ if (error.lineText) {
12
+ error.lineText = error.lineText.replaceAll(" ", " ");
13
+ console.log(`${chalk.black.bgWhite(error.range.start.line)} ${error.lineText}`);
14
+ let numberLength = error.range.start.line.toString().length;
15
+ let spacerLength = error.range.start.character;
16
+ let squiggleLength = error.range.start.line === error.range.end.line ? error.range.end.character - error.range.start.character : error.lineText.length - error.range.start.character;
17
+ console.log(`${chalk.black.bgWhite(" ".repeat(numberLength))} ${" ".repeat(spacerLength)}${chalk.red("~").repeat(squiggleLength)}`);
18
+ }
19
+ console.log();
20
+ }
21
+ }
22
+ //#endregion
23
+ //#region src/bin/index.ts
24
+ let errors = [];
25
+ let pathArg = process.argv[2];
26
+ if (!pathArg) {
27
+ pathArg = process.cwd();
28
+ errors = check(pathArg);
29
+ } else {
30
+ if (!fs.existsSync(pathArg)) pathArg = path.join(process.cwd(), pathArg);
31
+ if (!fs.existsSync(pathArg)) console.log("Path not found", process.argv[2]);
32
+ else if (fs.lstatSync(pathArg).isDirectory()) errors = check(pathArg);
33
+ else errors = check$1(pathArg);
34
+ }
35
+ if (errors.length > 0) {
36
+ console.log();
37
+ printErrors(path.dirname(pathArg), errors);
38
+ console.log(`Found ${chalk.red(errors.length)} error${errors.length === 1 ? "" : "s"}`);
39
+ } else console.log("No errors found");
40
+ //#endregion
41
+ export {};
42
+
43
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["checkFile"],"sources":["../../src/printErrors.ts","../../src/bin/index.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport path from \"node:path\";\nimport type Diagnostic from \"./types/Diagnostic\";\n\nexport default function printErrors(folder: string, errors: Diagnostic[]): void {\n\terrors.sort((a, b) => a.path.localeCompare(b.path));\n\n\tfor (let error of errors) {\n\t\tconsole.log(\n\t\t\t`${chalk.green(path.relative(folder, error.path))}:${chalk.yellow(error.range.start.line)}:${chalk.yellow(error.range.start.character)} - ${chalk.red(\"error\")}${error.code ? chalk.gray(` TS${error.code}`) : \"\"}: ${error.message}`,\n\t\t);\n\t\tif (error.lineText) {\n\t\t\t// HACK: If I were less lazy I'd replace tabs with 4 spaces and adjust positions\n\t\t\terror.lineText = error.lineText.replaceAll(\"\\t\", \" \");\n\t\t\tconsole.log(`${chalk.black.bgWhite(error.range.start.line)} ${error.lineText}`);\n\t\t\tlet numberLength = error.range.start.line.toString().length;\n\t\t\tlet spacerLength = error.range.start.character;\n\t\t\tlet squiggleLength =\n\t\t\t\terror.range.start.line === error.range.end.line\n\t\t\t\t\t? error.range.end.character - error.range.start.character\n\t\t\t\t\t: error.lineText.length - error.range.start.character;\n\t\t\tconsole.log(\n\t\t\t\t`${chalk.black.bgWhite(\" \".repeat(numberLength))} ${\" \".repeat(spacerLength)}${chalk.red(\"~\").repeat(squiggleLength)}`,\n\t\t\t);\n\t\t}\n\t\tconsole.log();\n\t}\n}\n","#! /usr/bin/env node\nimport chalk from \"chalk\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport check from \"../check\";\nimport checkFile from \"../checkFile\";\nimport printErrors from \"../printErrors\";\nimport type Diagnostic from \"../types/Diagnostic\";\n\nlet errors: Diagnostic[] = [];\n\nlet pathArg = process.argv[2];\nif (!pathArg) {\n\tpathArg = process.cwd();\n\terrors = check(pathArg);\n} else {\n\tif (!fs.existsSync(pathArg)) {\n\t\tpathArg = path.join(process.cwd(), pathArg);\n\t}\n\tif (!fs.existsSync(pathArg)) {\n\t\tconsole.log(\"Path not found\", process.argv[2]);\n\t} else if (fs.lstatSync(pathArg).isDirectory()) {\n\t\terrors = check(pathArg);\n\t} else {\n\t\terrors = checkFile(pathArg);\n\t}\n}\n\nif (errors.length > 0) {\n\tconsole.log();\n\tprintErrors(path.dirname(pathArg), errors);\n\tconsole.log(`Found ${chalk.red(errors.length)} error${errors.length === 1 ? \"\" : \"s\"}`);\n} else {\n\tconsole.log(\"No errors found\");\n}\n"],"mappings":";;;;;;AAIA,SAAwB,YAAY,QAAgB,QAA4B;CAC/E,OAAO,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;CAElD,KAAK,IAAI,SAAS,QAAQ;EACzB,QAAQ,IACP,GAAG,MAAM,MAAM,KAAK,SAAS,QAAQ,MAAM,IAAI,CAAC,EAAE,GAAG,MAAM,OAAO,MAAM,MAAM,MAAM,IAAI,EAAE,GAAG,MAAM,OAAO,MAAM,MAAM,MAAM,SAAS,EAAE,KAAK,MAAM,IAAI,OAAO,IAAI,MAAM,OAAO,MAAM,KAAK,MAAM,MAAM,MAAM,IAAI,GAAG,IAAI,MAAM,SAC7N;EACA,IAAI,MAAM,UAAU;GAEnB,MAAM,WAAW,MAAM,SAAS,WAAW,KAAM,GAAG;GACpD,QAAQ,IAAI,GAAG,MAAM,MAAM,QAAQ,MAAM,MAAM,MAAM,IAAI,EAAE,GAAG,MAAM,UAAU;GAC9E,IAAI,eAAe,MAAM,MAAM,MAAM,KAAK,SAAS,CAAC,CAAC;GACrD,IAAI,eAAe,MAAM,MAAM,MAAM;GACrC,IAAI,iBACH,MAAM,MAAM,MAAM,SAAS,MAAM,MAAM,IAAI,OACxC,MAAM,MAAM,IAAI,YAAY,MAAM,MAAM,MAAM,YAC9C,MAAM,SAAS,SAAS,MAAM,MAAM,MAAM;GAC9C,QAAQ,IACP,GAAG,MAAM,MAAM,QAAQ,IAAI,OAAO,YAAY,CAAC,EAAE,GAAG,IAAI,OAAO,YAAY,IAAI,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,cAAc,GACpH;EACD;EACA,QAAQ,IAAI;CACb;AACD;;;AClBA,IAAI,SAAuB,CAAC;AAE5B,IAAI,UAAU,QAAQ,KAAK;AAC3B,IAAI,CAAC,SAAS;CACb,UAAU,QAAQ,IAAI;CACtB,SAAS,MAAM,OAAO;AACvB,OAAO;CACN,IAAI,CAAC,GAAG,WAAW,OAAO,GACzB,UAAU,KAAK,KAAK,QAAQ,IAAI,GAAG,OAAO;CAE3C,IAAI,CAAC,GAAG,WAAW,OAAO,GACzB,QAAQ,IAAI,kBAAkB,QAAQ,KAAK,EAAE;MACvC,IAAI,GAAG,UAAU,OAAO,CAAC,CAAC,YAAY,GAC5C,SAAS,MAAM,OAAO;MAEtB,SAASA,QAAU,OAAO;AAE5B;AAEA,IAAI,OAAO,SAAS,GAAG;CACtB,QAAQ,IAAI;CACZ,YAAY,KAAK,QAAQ,OAAO,GAAG,MAAM;CACzC,QAAQ,IAAI,SAAS,MAAM,IAAI,OAAO,MAAM,EAAE,QAAQ,OAAO,WAAW,IAAI,KAAK,KAAK;AACvF,OACC,QAAQ,IAAI,iBAAiB"}
@@ -0,0 +1,446 @@
1
+ import tsvfs from "@typescript/vfs";
2
+ import chalk from "chalk";
3
+ import fg from "fast-glob";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import ts from "typescript";
7
+ import path$1 from "path";
8
+ import { build, parse } from "@torpor/view/compile";
9
+ //#region src/loadVts.ts
10
+ let vts = {
11
+ env: void 0,
12
+ lang: void 0,
13
+ projectRoot: "",
14
+ configPath: void 0,
15
+ config: {
16
+ options: {
17
+ target: ts.ScriptTarget.ES2022,
18
+ module: ts.ModuleKind.ESNext,
19
+ moduleResolution: ts.ModuleResolutionKind.Bundler,
20
+ esModuleInterop: true
21
+ },
22
+ include: [],
23
+ exclude: []
24
+ },
25
+ virtualFiles: /* @__PURE__ */ new Map(),
26
+ virtualFileMaps: /* @__PURE__ */ new Map()
27
+ };
28
+ function loadVts(vtsPath) {
29
+ if (vts.env === void 0) {
30
+ vts.projectRoot = path$1.join(vtsPath, ".");
31
+ while (vts.projectRoot && !fs.existsSync(path$1.join(vts.projectRoot, "node_modules"))) vts.projectRoot = path$1.join(vts.projectRoot, "..");
32
+ if (!vts.projectRoot) {
33
+ console.log("No project root found");
34
+ return;
35
+ }
36
+ try {
37
+ let fileConfig = loadTypeScriptConfig();
38
+ if (fileConfig?.options) vts.config = {
39
+ options: fileConfig.options,
40
+ include: fileConfig.raw.include ?? [],
41
+ exclude: fileConfig.raw.exclude ?? []
42
+ };
43
+ } catch {
44
+ console.log("No tsconfig.json file found, using default");
45
+ }
46
+ const system = tsvfs.createFSBackedSystem(vts.virtualFiles, vts.projectRoot, ts);
47
+ vts.env = tsvfs.createVirtualTypeScriptEnvironment(system, [], ts, vts.config.options);
48
+ vts.lang = vts.env.languageService;
49
+ console.log("Torpor type checking loaded");
50
+ }
51
+ return vts;
52
+ }
53
+ function loadTypeScriptConfig() {
54
+ const configFileName = ts.findConfigFile(vts.projectRoot, ts.sys.fileExists);
55
+ if (configFileName) {
56
+ vts.configPath = path$1.dirname(configFileName);
57
+ const configFile = ts.readConfigFile(configFileName, ts.sys.readFile);
58
+ return ts.parseJsonConfigFileContent(configFile.config, ts.sys, vts.projectRoot);
59
+ }
60
+ }
61
+ //#endregion
62
+ //#region src/pathReplace.ts
63
+ function pathReplace(pattern, replacement, value) {
64
+ pattern = "^" + pattern.replaceAll("*", "(.+?)");
65
+ replacement = replacement.replaceAll("*", "$1");
66
+ const regex1 = new RegExp(pattern);
67
+ return value.replace(regex1, replacement);
68
+ }
69
+ //#endregion
70
+ //#region src/transformDocument.ts
71
+ function transformDocument(vts, filename, source, debug = false) {
72
+ try {
73
+ const parsed = parse(source);
74
+ if (!parsed.ok) return {
75
+ ok: false,
76
+ errors: parsed.errors.map((e) => {
77
+ let lineTextStart = e.startIndex;
78
+ while (lineTextStart >= 0) {
79
+ if (source[lineTextStart] === "\n") {
80
+ lineTextStart++;
81
+ break;
82
+ }
83
+ lineTextStart--;
84
+ }
85
+ let lineTextEnd = source.indexOf("\n", e.startIndex);
86
+ if (lineTextEnd === -1) lineTextEnd = void 0;
87
+ return {
88
+ path: filename,
89
+ message: e.message,
90
+ range: {
91
+ start: {
92
+ line: e.startLine,
93
+ character: e.startChar
94
+ },
95
+ end: {
96
+ line: e.endLine,
97
+ character: e.endChar
98
+ }
99
+ },
100
+ lineText: source.substring(lineTextStart, lineTextEnd)
101
+ };
102
+ }),
103
+ content: "",
104
+ map: []
105
+ };
106
+ let { code, map } = build(parsed.template, { mapped: true });
107
+ code = importComponentFiles(vts, filename, code, map, debug);
108
+ return {
109
+ ok: true,
110
+ errors: [],
111
+ content: code,
112
+ map
113
+ };
114
+ } catch (ex) {
115
+ const message = ex instanceof Error ? ex.stack : String(ex);
116
+ console.log("Failed to compile", filename);
117
+ console.log(message);
118
+ return {
119
+ ok: false,
120
+ errors: [],
121
+ content: "",
122
+ map: []
123
+ };
124
+ }
125
+ }
126
+ function importComponentFiles(vts, filename, content, map, _debug = false) {
127
+ if (!/^\s*import\s+(.+?)\s+from\s+(.+?);*\s*$/ms.test(content)) return content;
128
+ const first = map.shift();
129
+ const filepath = path.dirname(filename);
130
+ let moved = 0;
131
+ let newMaps = [];
132
+ for (let i = 0; i < first.script.length; i++) if (first.script[i] === "/") {
133
+ if (first.script[i + 1] === "/") i = first.script.indexOf("\n", i);
134
+ else if (first.script[i + 1] === "*") i = first.script.indexOf("*/", i);
135
+ if (i === -1) return content;
136
+ } else if (first.script[i] === "i") {
137
+ const match = first.script.substring(i).match(/import\s+(.+?)\s+from\s+(.+?);*\s*$/ms);
138
+ if (match === null) continue;
139
+ const oldImport = match[0];
140
+ let importFile = match[2];
141
+ if (importFile.startsWith("'") && importFile.endsWith("'") || importFile.startsWith("\"") && importFile.endsWith("\"")) importFile = importFile.substring(1, importFile.length - 1);
142
+ if (!importFile.endsWith(".torp")) {
143
+ newMaps.push({
144
+ script: oldImport,
145
+ source: {
146
+ start: i,
147
+ end: i + oldImport.length
148
+ },
149
+ compiled: {
150
+ start: first.compiled.start + i + moved,
151
+ end: first.compiled.start + i + moved + oldImport.length
152
+ }
153
+ });
154
+ continue;
155
+ }
156
+ let typeFile = importFile.startsWith(".") ? path.join(filepath, importFile) : importFile;
157
+ if (vts.configPath && vts.config.options.paths) {
158
+ const oldTypeFile = typeFile;
159
+ for (let [srcGlob, paths] of Object.entries(vts.config.options.paths)) for (let destGlob of paths) typeFile = pathReplace(srcGlob, destGlob, typeFile);
160
+ if (typeFile !== oldTypeFile && typeFile.startsWith(".")) typeFile = path.join(vts.configPath, typeFile);
161
+ }
162
+ const key = typeFile.replace(/\.torp$/, ".ts");
163
+ if (!vts.virtualFiles.has(key) && fs.existsSync(typeFile)) {
164
+ vts.virtualFiles.set(key, "");
165
+ const typeSource = fs.readFileSync(typeFile, "utf8");
166
+ const { content } = transformDocument(vts, typeFile, typeSource);
167
+ vts.virtualFiles.set(key, content);
168
+ vts.env.createFile(key, content);
169
+ }
170
+ let oldLength = content.length;
171
+ let newValue = typeFile.replace(".torp", ".ts");
172
+ let newImport = oldImport.replace(importFile, newValue);
173
+ content = content.replace(oldImport, newImport);
174
+ let diff = content.length - oldLength;
175
+ for (let mapped of map) {
176
+ mapped.compiled.start += diff;
177
+ mapped.compiled.end += diff;
178
+ }
179
+ newMaps.push({
180
+ script: oldImport,
181
+ source: {
182
+ start: i,
183
+ end: i + oldImport.length
184
+ },
185
+ compiled: {
186
+ start: first.compiled.start + i + moved,
187
+ end: first.compiled.start + i + moved + newImport.length
188
+ }
189
+ });
190
+ moved += diff;
191
+ i += oldImport.length;
192
+ }
193
+ map.unshift(...newMaps);
194
+ return content;
195
+ }
196
+ //#endregion
197
+ //#region src/loadDocument.ts
198
+ function loadDocument(filename) {
199
+ const key = filename.replace(/\.torp$/, ".ts");
200
+ const vts = loadVts(filename);
201
+ if (vts === void 0) return {
202
+ ok: false,
203
+ errors: []
204
+ };
205
+ const text = fs.readFileSync(filename, "utf-8");
206
+ if (filename.endsWith(".torp")) {
207
+ const transformed = transformDocument(vts, filename, text);
208
+ if (!transformed.ok) return {
209
+ ok: false,
210
+ errors: transformed.errors
211
+ };
212
+ const { content, map } = transformed;
213
+ updateVirtualFile(vts, key, content, filename, map);
214
+ return {
215
+ ok: true,
216
+ filename,
217
+ key,
218
+ text,
219
+ content,
220
+ map,
221
+ vts
222
+ };
223
+ } else {
224
+ updateVirtualFile(vts, key, text, filename, []);
225
+ return {
226
+ ok: true,
227
+ filename,
228
+ key,
229
+ text,
230
+ content: text,
231
+ map: [],
232
+ vts
233
+ };
234
+ }
235
+ }
236
+ function updateVirtualFile(vts, key, content, sourceFile, map) {
237
+ if (!vts.virtualFiles.has(key)) vts.env.createFile(key, content);
238
+ else vts.env.updateFile(key, content);
239
+ vts.virtualFiles.set(key, content);
240
+ vts.virtualFileMaps.set(key, {
241
+ sourceFile,
242
+ map
243
+ });
244
+ }
245
+ //#endregion
246
+ //#region src/processErrors.ts
247
+ function processErrors(vts, errors) {
248
+ return errors.map((d) => {
249
+ let message = getMessageText(d);
250
+ if (d.file === void 0) return {
251
+ path: "",
252
+ message,
253
+ range: {
254
+ start: {
255
+ line: 0,
256
+ character: 0
257
+ },
258
+ end: {
259
+ line: 0,
260
+ character: 0
261
+ }
262
+ }
263
+ };
264
+ let filename = d.file.fileName;
265
+ let map = [];
266
+ if (vts.virtualFileMaps.has(filename)) {
267
+ let transformed = vts.virtualFileMaps.get(filename);
268
+ filename = transformed.sourceFile;
269
+ map = transformed.map;
270
+ }
271
+ const source = fs.readFileSync(filename, "utf-8");
272
+ let lineText;
273
+ if (!filename.endsWith(".torp")) {
274
+ let start = {
275
+ line: 0,
276
+ character: 0
277
+ };
278
+ let end = {
279
+ line: 0,
280
+ character: 0
281
+ };
282
+ if (d.start !== void 0) {
283
+ let lineMap = d.file.lineMap;
284
+ if (lineMap === void 0) {
285
+ lineMap = [0];
286
+ for (let i = 0; i < source.length; i++) if (source[i] === "\n") lineMap.push(i);
287
+ }
288
+ start.line = (lineMap.findIndex((l) => l > d.start) ?? 1) - 1;
289
+ start.character = d.start - lineMap[start.line] - 1;
290
+ let endx = d.start + (d.length ?? 0);
291
+ end.line = (lineMap.findIndex((l) => l >= endx) ?? 1) - 1;
292
+ end.character = endx - lineMap[end.line] - 1;
293
+ let lineStart = lineMap[start.line] + 1;
294
+ let lineEnd = lineMap[start.line + 1];
295
+ lineText = source.substring(lineStart, lineEnd);
296
+ }
297
+ return {
298
+ path: filename,
299
+ message,
300
+ range: {
301
+ start,
302
+ end
303
+ },
304
+ lineText
305
+ };
306
+ }
307
+ let start = d.start ?? 0;
308
+ let end = (d.start ?? 0) + (d.length ?? 0);
309
+ let mapped = map.find((m) => start >= m.compiled.start && end <= m.compiled.end);
310
+ if (message.startsWith("This import uses a '.ts' extension to resolve") || /Cannot find module '(.+?)\?raw'/.test(message)) {
311
+ mapped = void 0;
312
+ message = "!";
313
+ }
314
+ if (!mapped) return {
315
+ path: filename,
316
+ message,
317
+ range: {
318
+ start: {
319
+ line: 0,
320
+ character: 0
321
+ },
322
+ end: {
323
+ line: 0,
324
+ character: 0
325
+ }
326
+ }
327
+ };
328
+ let sourceStart = mapped.source.start + start - mapped.compiled.start;
329
+ let sourceEnd = mapped.source.start + end - mapped.compiled.start;
330
+ if (sourceStart > mapped.source.end) {
331
+ sourceStart = mapped.source.start;
332
+ sourceEnd = mapped.source.end;
333
+ }
334
+ if (sourceEnd > mapped.source.end) sourceEnd = mapped.source.end;
335
+ let lastLineStart = 0;
336
+ let startLine = 0;
337
+ for (let i = 0; i < sourceStart; i++) if (source[i] === "\n") {
338
+ lastLineStart = i + 1;
339
+ startLine++;
340
+ }
341
+ let startChar = sourceStart - lastLineStart;
342
+ let lastLineEnd = source.indexOf("\n", lastLineStart + 1);
343
+ if (lastLineEnd === -1) lastLineEnd = void 0;
344
+ lineText = source.substring(lastLineStart, lastLineEnd);
345
+ let endLine = startLine;
346
+ for (let i = sourceStart; i < sourceEnd; i++) if (source[i] === "\n") {
347
+ lastLineStart = i;
348
+ endLine++;
349
+ }
350
+ let endChar = sourceEnd - lastLineStart;
351
+ return {
352
+ path: filename,
353
+ message,
354
+ code: d.code,
355
+ range: {
356
+ start: {
357
+ line: startLine,
358
+ character: startChar
359
+ },
360
+ end: {
361
+ line: endLine,
362
+ character: endChar
363
+ }
364
+ },
365
+ lineText
366
+ };
367
+ }).filter((d) => d.message !== "!");
368
+ }
369
+ function getMessageText(d) {
370
+ if (typeof d.messageText === "string") return d.messageText;
371
+ else {
372
+ let messages = [];
373
+ getMessages(d.messageText, messages);
374
+ return messages.map((m, i) => " ".repeat(i * 2) + m).join("\n");
375
+ }
376
+ }
377
+ function getMessages(chain, messages) {
378
+ messages.push(chain.messageText);
379
+ if (chain.next !== void 0) for (let next of chain.next) getMessages(next, messages);
380
+ }
381
+ //#endregion
382
+ //#region src/check.ts
383
+ function check$1(folder) {
384
+ if (!fs.existsSync(folder)) folder = path.join(process.cwd(), folder);
385
+ console.log("Checking files in", folder);
386
+ const vts = loadVts(folder);
387
+ if (vts === void 0) return [];
388
+ let pathToGlob = (f) => {
389
+ f = fg.convertPathToPattern(f).replaceAll("\\*", "*");
390
+ if (!f.includes("*")) {
391
+ if (!f.endsWith("/")) f += "/";
392
+ f += "**";
393
+ }
394
+ return f;
395
+ };
396
+ let include = vts.config.include.map(pathToGlob);
397
+ if (include.length === 0) include.push("**");
398
+ const ignore = vts.config.exclude.map(pathToGlob);
399
+ let files = fg.globSync(include, {
400
+ cwd: folder,
401
+ ignore
402
+ }).filter((f) => f.endsWith(".js") || f.endsWith(".ts") || f.endsWith(".torp"));
403
+ console.log(`Found ${chalk.green(files.length)} file${files.length === 1 ? "" : "s"} to check`);
404
+ let errors = [];
405
+ for (let file of files) {
406
+ file = path.join(folder, file);
407
+ const loaded = loadDocument(file);
408
+ if (!loaded.ok) errors.push(...loaded.errors);
409
+ }
410
+ const host = tsvfs.createVirtualCompilerHost(vts.env.sys, vts.config.options, ts);
411
+ const program = ts.createProgram({
412
+ rootNames: [...vts.virtualFiles.keys()],
413
+ options: vts.config.options,
414
+ host: host.compilerHost
415
+ });
416
+ const compileErrors = program.getSemanticDiagnostics().concat(program.getDeclarationDiagnostics()).concat(program.getConfigFileParsingDiagnostics()).concat(program.getGlobalDiagnostics()).concat(program.getOptionsDiagnostics()).concat(program.getSyntacticDiagnostics());
417
+ errors.push(...processErrors(vts, compileErrors));
418
+ return errors;
419
+ }
420
+ //#endregion
421
+ //#region src/validateScript.ts
422
+ function validateScript(filename) {
423
+ try {
424
+ const transformed = loadDocument(filename);
425
+ if (!transformed.ok) {
426
+ if (!transformed.ok) return transformed.errors;
427
+ }
428
+ const { key, vts } = transformed;
429
+ vts.lang.cleanupSemanticCache();
430
+ return processErrors(vts, [...vts.lang.getSyntacticDiagnostics(key), ...vts.lang.getSemanticDiagnostics(key)]);
431
+ } catch (ex) {
432
+ console.log("VALIDATE ERROR:", ex);
433
+ return [];
434
+ }
435
+ }
436
+ //#endregion
437
+ //#region src/checkFile.ts
438
+ function check(file) {
439
+ if (!fs.existsSync(file)) file = path.join(process.cwd(), file);
440
+ console.log("Checking file", file);
441
+ return validateScript(file);
442
+ }
443
+ //#endregion
444
+ export { check$1 as n, check as t };
445
+
446
+ //# sourceMappingURL=checkFile-BvvjrnaS.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkFile-BvvjrnaS.mjs","names":["path","check"],"sources":["../src/loadVts.ts","../src/pathReplace.ts","../src/transformDocument.ts","../src/loadDocument.ts","../src/processErrors.ts","../src/check.ts","../src/validateScript.ts","../src/checkFile.ts"],"sourcesContent":["import tsvfs from \"@typescript/vfs\";\nimport fs from \"node:fs\";\nimport path from \"path\";\nimport ts, { type LanguageService } from \"typescript\";\nimport type SourceMap from \"./types/SourceMap\";\nimport type VirtualTypeScript from \"./types/VirtualTypeScript\";\n\nlet vts: VirtualTypeScript = {\n\t// @ts-ignore This will definitely be set\n\tenv: undefined,\n\t// @ts-ignore This will definitely be set\n\tlang: undefined,\n\tprojectRoot: \"\",\n\tconfigPath: undefined,\n\t// This is just the default config, it should be overwritten by the one from\n\t// the user's tsconfig.json\n\tconfig: {\n\t\toptions: {\n\t\t\ttarget: ts.ScriptTarget.ES2022,\n\t\t\tmodule: ts.ModuleKind.ESNext,\n\t\t\tmoduleResolution: ts.ModuleResolutionKind.Bundler,\n\t\t\tesModuleInterop: true,\n\t\t},\n\t\tinclude: [],\n\t\texclude: [],\n\t},\n\tvirtualFiles: new Map<string, string>(),\n\tvirtualFileMaps: new Map<string, { sourceFile: string; map: SourceMap[] }>(),\n};\n\nexport default function loadVts(vtsPath: string): VirtualTypeScript | undefined {\n\tif (vts.env === undefined) {\n\t\t// If using imports where the types don't directly match up to\n\t\t// their FS representation (like the imports for node) then use\n\t\t// triple-slash directives to make sure globals are set up\n\t\t// first.\n\t\t//const content = `\n\t\t//\t/// <reference types=\"node\" />\n\t\t//\timport * as path from 'path';\n\t\t//\tpath.`.replaceAll(/\\s+/, \" \").trim();\n\n\t\t// By providing a project root, the system knows how to resolve\n\t\t// node_modules correctly\n\t\tvts.projectRoot = path.join(vtsPath, \".\");\n\t\twhile (vts.projectRoot && !fs.existsSync(path.join(vts.projectRoot, \"node_modules\"))) {\n\t\t\tvts.projectRoot = path.join(vts.projectRoot, \"..\");\n\t\t}\n\t\tif (!vts.projectRoot) {\n\t\t\tconsole.log(\"No project root found\");\n\t\t\treturn;\n\t\t}\n\n\t\t// Maybe load tsconfig from a file\n\t\t// TODO: reload if the file is changed\n\t\ttry {\n\t\t\tlet fileConfig = loadTypeScriptConfig();\n\t\t\tif (fileConfig?.options) {\n\t\t\t\tvts.config = {\n\t\t\t\t\toptions: fileConfig.options,\n\t\t\t\t\tinclude: fileConfig.raw.include ?? [],\n\t\t\t\t\texclude: fileConfig.raw.exclude ?? [],\n\t\t\t\t};\n\t\t\t}\n\t\t} catch {\n\t\t\tconsole.log(\"No tsconfig.json file found, using default\");\n\t\t}\n\n\t\tconst system = tsvfs.createFSBackedSystem(vts.virtualFiles, vts.projectRoot, ts);\n\t\tvts.env = tsvfs.createVirtualTypeScriptEnvironment(system, [], ts, vts.config.options);\n\t\tvts.lang = vts.env.languageService as LanguageService;\n\n\t\tconsole.log(\"Torpor type checking loaded\");\n\t}\n\treturn vts;\n}\n\nfunction loadTypeScriptConfig(): Record<string, any> | undefined {\n\tconst configFileName = ts.findConfigFile(vts.projectRoot, ts.sys.fileExists);\n\tif (configFileName) {\n\t\tvts.configPath = path.dirname(configFileName);\n\t\tconst configFile = ts.readConfigFile(configFileName, ts.sys.readFile);\n\t\treturn ts.parseJsonConfigFileContent(configFile.config, ts.sys, vts.projectRoot);\n\t}\n}\n","// TODO: Implement more logic from https://www.typescriptlang.org/docs/handbook/modules/reference.html#paths\nexport default function pathReplace(pattern: string, replacement: string, value: string): string {\n\tpattern = \"^\" + pattern.replaceAll(\"*\", \"(.+?)\");\n\treplacement = replacement.replaceAll(\"*\", \"$1\");\n\n\tconst regex1 = new RegExp(pattern);\n\treturn value.replace(regex1, replacement);\n}\n","import { build, parse } from \"@torpor/view/compile\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport pathReplace from \"./pathReplace\";\nimport type Diagnostic from \"./types/Diagnostic\";\nimport type SourceMap from \"./types/SourceMap\";\nimport type VirtualTypeScript from \"./types/VirtualTypeScript\";\n\ninterface TransformResult {\n\tok: boolean;\n\terrors: Diagnostic[];\n\tcontent: string;\n\tmap: SourceMap[];\n}\n\nexport default function transformDocument(\n\tvts: VirtualTypeScript,\n\tfilename: string,\n\tsource: string,\n\tdebug = false,\n): TransformResult {\n\ttry {\n\t\t// Build the main file as a component\n\t\tconst parsed = parse(source);\n\n\t\t// If not ok, don't validate\n\t\tif (!parsed.ok) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terrors: parsed.errors.map((e) => {\n\t\t\t\t\tlet lineTextStart = e.startIndex;\n\t\t\t\t\twhile (lineTextStart >= 0) {\n\t\t\t\t\t\tif (source[lineTextStart] === \"\\n\") {\n\t\t\t\t\t\t\tlineTextStart++;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlineTextStart--;\n\t\t\t\t\t}\n\t\t\t\t\tlet lineTextEnd: number | undefined = source.indexOf(\"\\n\", e.startIndex);\n\t\t\t\t\tif (lineTextEnd === -1) lineTextEnd = undefined;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpath: filename,\n\t\t\t\t\t\tmessage: e.message,\n\t\t\t\t\t\trange: {\n\t\t\t\t\t\t\tstart: { line: e.startLine, character: e.startChar },\n\t\t\t\t\t\t\tend: { line: e.endLine, character: e.endChar },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tlineText: source.substring(lineTextStart, lineTextEnd),\n\t\t\t\t\t} satisfies Diagnostic;\n\t\t\t\t}),\n\t\t\t\tcontent: \"\",\n\t\t\t\tmap: [],\n\t\t\t};\n\t\t}\n\n\t\tlet { code, map } = build(parsed.template!, { mapped: true });\n\n\t\tcode = importComponentFiles(vts, filename, code, map, debug);\n\n\t\t//console.log(code);\n\t\t//console.log(map);\n\n\t\treturn {\n\t\t\tok: true,\n\t\t\terrors: [],\n\t\t\tcontent: code,\n\t\t\tmap,\n\t\t};\n\t} catch (ex) {\n\t\tconst message = ex instanceof Error ? ex.stack : String(ex);\n\t\tconsole.log(\"Failed to compile\", filename);\n\t\tconsole.log(message);\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: [],\n\t\t\tcontent: \"\",\n\t\t\tmap: [],\n\t\t};\n\t}\n}\n\nfunction importComponentFiles(\n\tvts: VirtualTypeScript,\n\tfilename: string,\n\tcontent: string,\n\tmap: SourceMap[],\n\t_debug = false,\n): string {\n\tif (!/^\\s*import\\s+(.+?)\\s+from\\s+(.+?);*\\s*$/ms.test(content)) {\n\t\treturn content;\n\t}\n\n\t// Build imported component files and add them to the virtual file map\n\t// TODO: Handle files from node_modules? Might get done automatically by typescript-vfs\n\n\t// HACK: We're assuming that all imports are at the top of the file, and\n\t// that there are not multiple imports on the one line\n\tconst first = map.shift()!;\n\tconst filepath = path.dirname(filename);\n\n\tlet moved = 0;\n\tlet newMaps: SourceMap[] = [];\n\n\tfor (let i = 0; i < first.script.length; i++) {\n\t\tif (first.script[i] === \"/\") {\n\t\t\t// Skip comments\n\t\t\tif (first.script[i + 1] === \"/\") {\n\t\t\t\ti = first.script.indexOf(\"\\n\", i);\n\t\t\t} else if (first.script[i + 1] === \"*\") {\n\t\t\t\ti = first.script.indexOf(\"*/\", i);\n\t\t\t}\n\t\t\tif (i === -1) {\n\t\t\t\treturn content;\n\t\t\t}\n\t\t} else if (first.script[i] === \"i\") {\n\t\t\tconst match = first.script.substring(i).match(/import\\s+(.+?)\\s+from\\s+(.+?);*\\s*$/ms);\n\t\t\tif (match === null) continue;\n\n\t\t\tconst oldImport = match[0];\n\t\t\t//const names = match[1];\n\t\t\tconst importedFile = match[2];\n\n\t\t\t// Strip quotes\n\t\t\tlet importFile = importedFile;\n\t\t\tif (\n\t\t\t\t(importFile.startsWith(\"'\") && importFile.endsWith(\"'\")) ||\n\t\t\t\t(importFile.startsWith('\"') && importFile.endsWith('\"'))\n\t\t\t) {\n\t\t\t\timportFile = importFile.substring(1, importFile.length - 1);\n\t\t\t}\n\n\t\t\t// Just map import files that aren't components\n\t\t\tif (!importFile.endsWith(\".torp\")) {\n\t\t\t\tnewMaps.push({\n\t\t\t\t\tscript: oldImport,\n\t\t\t\t\tsource: {\n\t\t\t\t\t\tstart: i,\n\t\t\t\t\t\tend: i + oldImport.length,\n\t\t\t\t\t},\n\t\t\t\t\tcompiled: {\n\t\t\t\t\t\tstart: first.compiled.start + i + moved,\n\t\t\t\t\t\tend: first.compiled.start + i + moved + oldImport.length,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Get the absolute path of the import file\n\t\t\tlet typeFile = importFile.startsWith(\".\") ? path.join(filepath, importFile) : importFile;\n\n\t\t\t// Replace aliased paths from tsconfig.json\n\t\t\tif (vts.configPath && vts.config.options.paths) {\n\t\t\t\t// HACK: Get the longest match etc\n\t\t\t\tconst oldTypeFile = typeFile;\n\t\t\t\tfor (let [srcGlob, paths] of Object.entries(vts.config.options.paths)) {\n\t\t\t\t\tfor (let destGlob of paths) {\n\t\t\t\t\t\ttypeFile = pathReplace(srcGlob, destGlob, typeFile);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// The import may now be relative to the tsconfig file, so make it absolute\n\t\t\t\tif (typeFile !== oldTypeFile && typeFile.startsWith(\".\")) {\n\t\t\t\t\ttypeFile = path.join(vts.configPath, typeFile);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Create the virtual file for the component\n\t\t\tconst key = typeFile.replace(/\\.torp$/, \".ts\");\n\t\t\tif (!vts.virtualFiles.has(key) && fs.existsSync(typeFile)) {\n\t\t\t\t// Mark as in progress before transforming, so that circular\n\t\t\t\t// component imports don't recurse forever\n\t\t\t\tvts.virtualFiles.set(key, \"\");\n\t\t\t\tconst typeSource = fs.readFileSync(typeFile, \"utf8\");\n\t\t\t\tconst { content } = transformDocument(vts, typeFile, typeSource);\n\t\t\t\tvts.virtualFiles.set(key, content);\n\t\t\t\tvts.env.createFile(key, content);\n\t\t\t}\n\n\t\t\t// Replace the import file with the virtual file\n\t\t\tlet oldLength = content.length;\n\t\t\tlet newValue = typeFile.replace(\".torp\", \".ts\");\n\t\t\t// HACK: We could concat this if we could be bothered\n\t\t\tlet newImport = oldImport.replace(importFile, newValue);\n\t\t\tcontent = content.replace(oldImport, newImport);\n\n\t\t\t// Move subsequent ranges around\n\t\t\tlet diff = content.length - oldLength;\n\t\t\tfor (let mapped of map) {\n\t\t\t\tmapped.compiled.start += diff;\n\t\t\t\tmapped.compiled.end += diff;\n\t\t\t}\n\n\t\t\t// Add a range for the changed import\n\t\t\tnewMaps.push({\n\t\t\t\tscript: oldImport,\n\t\t\t\tsource: {\n\t\t\t\t\tstart: i,\n\t\t\t\t\tend: i + oldImport.length,\n\t\t\t\t},\n\t\t\t\tcompiled: {\n\t\t\t\t\tstart: first.compiled.start + i + moved,\n\t\t\t\t\tend: first.compiled.start + i + moved + newImport.length,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tmoved += diff;\n\t\t\ti += oldImport.length;\n\t\t}\n\t}\n\n\tmap.unshift(...newMaps);\n\n\treturn content;\n}\n","import fs from \"node:fs\";\nimport loadVts from \"./loadVts\";\nimport transformDocument from \"./transformDocument\";\nimport type Diagnostic from \"./types/Diagnostic\";\nimport type SourceMap from \"./types/SourceMap\";\nimport type VirtualTypeScript from \"./types/VirtualTypeScript\";\n\ntype LoadResult =\n\t| { ok: false; errors: Diagnostic[] }\n\t| {\n\t\t\tok: true;\n\t\t\tfilename: string;\n\t\t\tkey: string;\n\t\t\ttext: string;\n\t\t\tcontent: string;\n\t\t\tmap: SourceMap[];\n\t\t\tvts: VirtualTypeScript;\n\t };\n\nexport function loadDocument(filename: string): LoadResult {\n\tconst key = filename.replace(/\\.torp$/, \".ts\");\n\n\tconst vts = loadVts(filename);\n\tif (vts === undefined) {\n\t\treturn { ok: false, errors: [] };\n\t}\n\n\tconst text = fs.readFileSync(filename, \"utf-8\");\n\tif (filename.endsWith(\".torp\")) {\n\t\tconst transformed = transformDocument(vts, filename, text);\n\t\tif (!transformed.ok) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terrors: transformed.errors,\n\t\t\t};\n\t\t}\n\t\tconst { content, map } = transformed;\n\t\tupdateVirtualFile(vts, key, content, filename, map);\n\t\treturn { ok: true, filename, key, text, content, map, vts: vts };\n\t} else {\n\t\tupdateVirtualFile(vts, key, text, filename, []);\n\t\treturn { ok: true, filename, key, text, content: text, map: [], vts: vts };\n\t}\n}\n\nfunction updateVirtualFile(\n\tvts: VirtualTypeScript,\n\tkey: string,\n\tcontent: string,\n\tsourceFile: string,\n\tmap: SourceMap[],\n) {\n\tif (!vts.virtualFiles.has(key)) {\n\t\tvts.env.createFile(key, content);\n\t} else {\n\t\tvts.env.updateFile(key, content);\n\t}\n\tvts.virtualFiles.set(key, content);\n\tvts.virtualFileMaps.set(key, { sourceFile, map });\n}\n","import fs from \"node:fs\";\nimport ts, { type DiagnosticMessageChain } from \"typescript\";\nimport type Diagnostic from \"./types/Diagnostic\";\nimport type SourceMap from \"./types/SourceMap\";\nimport type VirtualTypeScript from \"./types/VirtualTypeScript\";\n\nexport default function processErrors(\n\tvts: VirtualTypeScript,\n\terrors: ts.Diagnostic[],\n): Diagnostic[] {\n\treturn errors\n\t\t.map((d: ts.Diagnostic) => {\n\t\t\tlet message = getMessageText(d);\n\n\t\t\tif (d.file === undefined) {\n\t\t\t\treturn {\n\t\t\t\t\tpath: \"\",\n\t\t\t\t\tmessage,\n\t\t\t\t\trange: {\n\t\t\t\t\t\tstart: { line: 0, character: 0 },\n\t\t\t\t\t\tend: { line: 0, character: 0 },\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tlet filename = d.file.fileName;\n\t\t\tlet map: SourceMap[] = [];\n\t\t\tif (vts.virtualFileMaps.has(filename)) {\n\t\t\t\tlet transformed = vts.virtualFileMaps.get(filename)!;\n\t\t\t\tfilename = transformed.sourceFile;\n\t\t\t\tmap = transformed.map;\n\t\t\t}\n\t\t\tconst source = fs.readFileSync(filename, \"utf-8\");\n\t\t\tlet lineText: string | undefined;\n\t\t\tif (!filename.endsWith(\".torp\")) {\n\t\t\t\tlet start = { line: 0, character: 0 };\n\t\t\t\tlet end = { line: 0, character: 0 };\n\t\t\t\tif (d.start !== undefined) {\n\t\t\t\t\t// @ts-ignore we know this exists\n\t\t\t\t\tlet lineMap: number[] = d.file.lineMap;\n\t\t\t\t\tif (lineMap === undefined) {\n\t\t\t\t\t\tlineMap = [0];\n\t\t\t\t\t\tfor (let i = 0; i < source.length; i++) {\n\t\t\t\t\t\t\tif (source[i] === \"\\n\") lineMap.push(i);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// TODO: These need to be indexes\n\t\t\t\t\tstart.line = (lineMap.findIndex((l: number) => l > d.start!) ?? 1) - 1;\n\t\t\t\t\tstart.character = d.start - lineMap[start.line] - 1;\n\t\t\t\t\tlet endx = d.start! + (d.length ?? 0);\n\t\t\t\t\tend.line = (lineMap.findIndex((l: number) => l >= endx) ?? 1) - 1;\n\t\t\t\t\tend.character = endx - lineMap[end.line] - 1;\n\t\t\t\t\tlet lineStart = lineMap[start.line] + 1;\n\t\t\t\t\tlet lineEnd = lineMap[start.line + 1];\n\t\t\t\t\tlineText = source.substring(lineStart, lineEnd);\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tpath: filename,\n\t\t\t\t\tmessage,\n\t\t\t\t\trange: { start, end },\n\t\t\t\t\tlineText,\n\t\t\t\t} satisfies Diagnostic;\n\t\t\t}\n\n\t\t\t// Find the mapping between source and compiled, if it exists. If it\n\t\t\t// doesn't exist, the error must be in non-user code. Not great, but\n\t\t\t// the user doesn't need to know about it\n\t\t\tlet start = d.start ?? 0;\n\t\t\tlet end = (d.start ?? 0) + (d.length ?? 0);\n\t\t\tlet mapped = map.find((m: any) => start >= m.compiled.start && end <= m.compiled.end);\n\n\t\t\t// HACK: We don't care about these? Maybe there's a better way to\n\t\t\t// ignore/fix them\n\t\t\tif (\n\t\t\t\tmessage.startsWith(\"This import uses a '.ts' extension to resolve\") ||\n\t\t\t\t/Cannot find module '(.+?)\\?raw'/.test(message)\n\t\t\t) {\n\t\t\t\tmapped = undefined;\n\t\t\t\t// This special message will be filtered out\n\t\t\t\tmessage = \"!\";\n\t\t\t}\n\n\t\t\t//if (!mapped && message !== \"!\") {\n\t\t\t//\t// Log it for diagnostics\n\t\t\t//\tconsole.log(`Error${!mapped ? \" (unmapped)\" : \"\"}:`, message);\n\t\t\t//\t// @ts-ignore we know this exists\n\t\t\t//\tconst lineMap: number[] = d.file?.lineMap;\n\t\t\t//\tif (lineMap) {\n\t\t\t//\t\tconst line = (lineMap.findIndex((l: number) => l > start) ?? 1) - 1;\n\t\t\t//\t\tconst char = start - lineMap[line];\n\t\t\t//\t\tconsole.log(`(${line + 1}, ${char + 1}):`, content.split(\"\\n\")[line]);\n\t\t\t//\t}\n\t\t\t//}\n\n\t\t\t// HACK: Couldn't map back to the source, so just display it at the\n\t\t\t// first character\n\t\t\tif (!mapped) {\n\t\t\t\treturn {\n\t\t\t\t\tpath: filename,\n\t\t\t\t\tmessage,\n\t\t\t\t\trange: {\n\t\t\t\t\t\tstart: { line: 0, character: 0 },\n\t\t\t\t\t\tend: { line: 0, character: 0 },\n\t\t\t\t\t},\n\t\t\t\t} satisfies Diagnostic;\n\t\t\t}\n\n\t\t\t// We have the mapping, so we know roughly where in the\n\t\t\t// source the error occurs, but now we need to narrow it\n\t\t\t// down to the exact location\n\t\t\tlet sourceStart = mapped.source.start + start - mapped.compiled.start;\n\t\t\tlet sourceEnd = mapped.source.start + end - mapped.compiled.start;\n\t\t\t// HACK: If the translated mapping is outside of the source mapping,\n\t\t\t// just highlight the source mapping. It won't be 100% accurate, but\n\t\t\t// better than showing it way off in the middle of nowhere. This\n\t\t\t// happens e.g. when the $props are bad (as `<Component>` maps to\n\t\t\t// something like `Component($parent, $anchor, $props)`\n\t\t\tif (sourceStart > mapped.source.end) {\n\t\t\t\tsourceStart = mapped.source.start;\n\t\t\t\tsourceEnd = mapped.source.end;\n\t\t\t}\n\t\t\t// Same thing for if the error extends too far\n\t\t\tif (sourceEnd > mapped.source.end) {\n\t\t\t\tsourceEnd = mapped.source.end;\n\t\t\t}\n\n\t\t\t// TODO: Store this, so we don't need to start from 0 every time\n\t\t\tlet lastLineStart = 0;\n\t\t\tlet startLine = 0;\n\t\t\tfor (let i = 0; i < sourceStart; i++) {\n\t\t\t\tif (source[i] === \"\\n\") {\n\t\t\t\t\tlastLineStart = i + 1;\n\t\t\t\t\tstartLine++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet startChar = sourceStart - lastLineStart; /*- 1*/\n\n\t\t\tlet lastLineEnd: number | undefined = source.indexOf(\"\\n\", lastLineStart + 1);\n\t\t\tif (lastLineEnd === -1) lastLineEnd = undefined;\n\t\t\tlineText = source.substring(lastLineStart, lastLineEnd);\n\n\t\t\tlet endLine = startLine;\n\t\t\tfor (let i = sourceStart; i < sourceEnd; i++) {\n\t\t\t\tif (source[i] === \"\\n\") {\n\t\t\t\t\tlastLineStart = i;\n\t\t\t\t\tendLine++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet endChar = sourceEnd - lastLineStart; // - 1;\n\n\t\t\treturn {\n\t\t\t\tpath: filename,\n\t\t\t\tmessage,\n\t\t\t\tcode: d.code,\n\t\t\t\trange: {\n\t\t\t\t\tstart: {\n\t\t\t\t\t\tline: startLine,\n\t\t\t\t\t\tcharacter: startChar,\n\t\t\t\t\t},\n\t\t\t\t\tend: {\n\t\t\t\t\t\tline: endLine,\n\t\t\t\t\t\tcharacter: endChar,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tlineText,\n\t\t\t} satisfies Diagnostic;\n\t\t})\n\t\t.filter((d) => d.message !== \"!\");\n}\n\nfunction getMessageText(d: ts.Diagnostic): string {\n\tif (typeof d.messageText === \"string\") {\n\t\treturn d.messageText;\n\t} else {\n\t\tlet messages: string[] = [];\n\t\tgetMessages(d.messageText, messages);\n\t\treturn messages.map((m, i) => \" \".repeat(i * 2) + m).join(\"\\n\");\n\t}\n}\n\nfunction getMessages(chain: DiagnosticMessageChain, messages: string[]) {\n\tmessages.push(chain.messageText);\n\tif (chain.next !== undefined) {\n\t\tfor (let next of chain.next) {\n\t\t\tgetMessages(next, messages);\n\t\t}\n\t}\n}\n","import tsvfs from \"@typescript/vfs\";\nimport chalk from \"chalk\";\nimport fg from \"fast-glob\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport ts from \"typescript\";\nimport { loadDocument } from \"./loadDocument\";\nimport loadVts from \"./loadVts\";\nimport processErrors from \"./processErrors\";\nimport type Diagnostic from \"./types/Diagnostic\";\n\nexport default function check(folder: string): Diagnostic[] {\n\tif (!fs.existsSync(folder)) {\n\t\tfolder = path.join(process.cwd(), folder);\n\t}\n\tconsole.log(\"Checking files in\", folder);\n\n\tconst vts = loadVts(folder);\n\tif (vts === undefined) {\n\t\treturn [];\n\t}\n\n\t// Convert tsconfig includes and excludes to globs\n\tlet pathToGlob = (f: string) => {\n\t\tf = fg.convertPathToPattern(f).replaceAll(\"\\\\*\", \"*\");\n\t\tif (!f.includes(\"*\")) {\n\t\t\tif (!f.endsWith(\"/\")) f += \"/\";\n\t\t\tf += \"**\";\n\t\t}\n\t\treturn f;\n\t};\n\tlet include = vts.config.include.map(pathToGlob);\n\tif (include.length === 0) {\n\t\tinclude.push(\"**\");\n\t}\n\tconst ignore = vts.config.exclude.map(pathToGlob);\n\n\t// Get the included files with supported extensions\n\tlet files: string[] = fg\n\t\t.globSync(include, { cwd: folder, ignore })\n\t\t.filter((f) => f.endsWith(\".js\") || f.endsWith(\".ts\") || f.endsWith(\".torp\"));\n\tconsole.log(`Found ${chalk.green(files.length)} file${files.length === 1 ? \"\" : \"s\"} to check`);\n\n\tlet errors: Diagnostic[] = [];\n\n\t// Transform files and gather transform errors\n\tfor (let file of files) {\n\t\tfile = path.join(folder, file);\n\t\tconst loaded = loadDocument(file);\n\t\tif (!loaded.ok) {\n\t\t\terrors.push(...loaded.errors);\n\t\t}\n\t}\n\n\t// Build the typescript program with all compiling files\n\tconst host = tsvfs.createVirtualCompilerHost(vts.env.sys, vts.config.options, ts);\n\tconst program = ts.createProgram({\n\t\trootNames: [...vts.virtualFiles.keys()],\n\t\toptions: vts.config.options,\n\t\thost: host.compilerHost,\n\t});\n\n\t// Get typescript to check the compiled files\n\tconst compileErrors = program\n\t\t.getSemanticDiagnostics()\n\t\t.concat(program.getDeclarationDiagnostics())\n\t\t.concat(program.getConfigFileParsingDiagnostics())\n\t\t.concat(program.getGlobalDiagnostics())\n\t\t.concat(program.getOptionsDiagnostics())\n\t\t.concat(program.getSyntacticDiagnostics());\n\terrors.push(...processErrors(vts, compileErrors));\n\n\treturn errors;\n}\n","import { loadDocument } from \"./loadDocument\";\nimport processErrors from \"./processErrors\";\nimport type Diagnostic from \"./types/Diagnostic\";\n\nexport default function validateScript(filename: string): Diagnostic[] {\n\ttry {\n\t\tconst transformed = loadDocument(filename);\n\t\tif (!transformed.ok) {\n\t\t\t// If there were parse or build errors, return them immediately\n\t\t\t// TODO: Do we want to clear the virtual file??\n\t\t\tif (!transformed.ok) {\n\t\t\t\treturn transformed.errors;\n\t\t\t}\n\t\t}\n\n\t\tconst { key, vts } = transformed;\n\n\t\t// HACK: Is this ok to do every check? We're doing it because otherwise\n\t\t// changes to linked files (e.g. adding or removing a field in an interface)\n\t\t// don't get picked up. But doing it here also means that it only happens\n\t\t// when the file is edited...\n\t\tvts.lang.cleanupSemanticCache();\n\n\t\tconst diagnostics = processErrors(vts, [\n\t\t\t...vts.lang.getSyntacticDiagnostics(key),\n\t\t\t...vts.lang.getSemanticDiagnostics(key),\n\t\t]);\n\n\t\treturn diagnostics;\n\t} catch (ex) {\n\t\tconsole.log(\"VALIDATE ERROR:\", ex);\n\t\treturn [];\n\t}\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type Diagnostic from \"./types/Diagnostic\";\nimport validateScript from \"./validateScript\";\n\nexport default function check(file: string): Diagnostic[] {\n\tif (!fs.existsSync(file)) {\n\t\tfile = path.join(process.cwd(), file);\n\t}\n\tconsole.log(\"Checking file\", file);\n\n\treturn validateScript(file);\n}\n"],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ //#region src/types/Diagnostic.d.ts
2
+ interface Diagnostic {
3
+ path: string;
4
+ message: string;
5
+ code?: number;
6
+ range: {
7
+ start: {
8
+ line: number;
9
+ character: number;
10
+ };
11
+ end: {
12
+ line: number;
13
+ character: number;
14
+ };
15
+ };
16
+ lineText?: string;
17
+ }
18
+ //#endregion
19
+ //#region src/check.d.ts
20
+ declare function check(folder: string): Diagnostic[];
21
+ //#endregion
22
+ //#region src/checkFile.d.ts
23
+ declare function check$1(file: string): Diagnostic[];
24
+ //#endregion
25
+ export { check, check$1 as checkFile };
26
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types/Diagnostic.ts","../src/check.ts","../src/checkFile.ts"],"mappings":";UAAyB;EACxB;EACA;EACA;EACA;IACC;MAAS;MAAc;;IACvB;MAAO;MAAc;;;EAEtB;;;;iBCGuB,MAAM,iBAAiB;;;iBCNvB,QAAM,eAAe"}
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import { n as check, t as check$1 } from "./checkFile-BvvjrnaS.mjs";
2
+ export { check, check$1 as checkFile };
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@torpor/check",
3
+ "version": "1.0.0",
4
+ "description": "Checks Torpor files for errors",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.mts",
9
+ "import": "./dist/index.mjs"
10
+ }
11
+ },
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "bin": {
19
+ "torp-check": "./dist/bin/index.js"
20
+ },
21
+ "scripts": {
22
+ "check": "tsgo --noEmit && pnpm dlx oxlint --type-aware",
23
+ "build": "tsgo --noEmit && vp pack",
24
+ "build:fix": "tsx scripts/postbuild.ts",
25
+ "build:watch": "vp pack --watch",
26
+ "test": "vp test"
27
+ },
28
+ "keywords": [],
29
+ "author": "",
30
+ "license": "ISC",
31
+ "dependencies": {
32
+ "@torpor/view": "workspace:^",
33
+ "@typescript/vfs": "^1.6.4",
34
+ "chalk": "^6.0.0",
35
+ "fast-glob": "^3.3.3"
36
+ },
37
+ "devDependencies": {
38
+ "@typescript/native-preview": "7.0.0-dev.20260707.2",
39
+ "tsx": "^4.23.5",
40
+ "typescript": "6.0.3",
41
+ "vite": "catalog:",
42
+ "vite-plus": "catalog:"
43
+ }
44
+ }