@danielx/civet 0.11.7 → 0.11.8

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.
@@ -0,0 +1,1188 @@
1
+ // source/ts-service/snapshot.civet
2
+ import ts from "typescript";
3
+ function fullDiffTextChangeRange(oldText, newText) {
4
+ const oldTextLength = oldText.length;
5
+ const newTextLength = newText.length;
6
+ const minLength = Math.min(oldTextLength, newTextLength);
7
+ for (let start = 0; start < minLength; start++) {
8
+ if (oldText[start] !== newText[start]) {
9
+ let end = oldTextLength;
10
+ let stop = minLength - start;
11
+ for (let i = 0; i < stop; i++) {
12
+ if (oldText[oldTextLength - i - 1] !== newText[newTextLength - i - 1]) {
13
+ break;
14
+ }
15
+ end--;
16
+ }
17
+ const length = end - start;
18
+ const newLength = length + (newTextLength - oldTextLength);
19
+ return {
20
+ span: { start, length },
21
+ newLength
22
+ };
23
+ }
24
+ }
25
+ return void 0;
26
+ }
27
+ function Snap(newText) {
28
+ const changeRanges = /* @__PURE__ */ new Map();
29
+ const snapshot = {
30
+ getText: (start, end) => newText.slice(start, end),
31
+ getLength: () => newText.length,
32
+ getChangeRange(oldSnapshot) {
33
+ if (!changeRanges.has(oldSnapshot)) {
34
+ changeRanges.set(oldSnapshot, void 0);
35
+ const oldText = oldSnapshot.getText(0, oldSnapshot.getLength());
36
+ const changeRange = fullDiffTextChangeRange(oldText, newText);
37
+ if (changeRange) {
38
+ changeRanges.set(oldSnapshot, changeRange);
39
+ }
40
+ }
41
+ return changeRanges.get(oldSnapshot);
42
+ }
43
+ };
44
+ return snapshot;
45
+ }
46
+
47
+ // source/ts-service/path.civet
48
+ import ts3 from "typescript";
49
+ import path from "node:path";
50
+
51
+ // source/ts-service/types.civet
52
+ import ts2 from "typescript";
53
+
54
+ // source/ts-service/path.civet
55
+ function getCanonicalFileName(fileName) {
56
+ fileName = path.normalize(fileName);
57
+ if (!(ts3.sys?.useCaseSensitiveFileNames ?? true)) {
58
+ fileName = fileName.toLowerCase();
59
+ }
60
+ return fileName;
61
+ }
62
+ var lastExtension = /(?:\.(?:[^./]+))?$/;
63
+ var lastTwoExtensions = /(\.[^./]*)(\.[^./]*)$/;
64
+ function getExtensionFromPath(p) {
65
+ const match = p.match(lastExtension);
66
+ if (!match) {
67
+ return "";
68
+ }
69
+ return match[0];
70
+ }
71
+ function getTranspiledExtensionsFromPath(p) {
72
+ const match = p.match(lastTwoExtensions);
73
+ if (!match) {
74
+ return;
75
+ }
76
+ return [match[1], match[2]];
77
+ }
78
+ function removeExtension(p) {
79
+ return p.replace(/\.[^\/.]+$/, "");
80
+ }
81
+ function remapFileName(fileName, transpilers) {
82
+ const [extension, target] = getTranspiledExtensionsFromPath(fileName) ?? [];
83
+ if (!extension) {
84
+ return fileName;
85
+ }
86
+ const transpiler = transpilers.get(extension);
87
+ if (!transpiler) {
88
+ return fileName;
89
+ }
90
+ if (transpiler.target === target) {
91
+ return removeExtension(fileName);
92
+ }
93
+ return fileName;
94
+ }
95
+
96
+ // source/ts-service/host.civet
97
+ import path3 from "node:path";
98
+ import ts5 from "typescript";
99
+ import {} from "typescript";
100
+
101
+ // source/ts-service/config.civet
102
+ import ts4 from "typescript";
103
+ import path2 from "node:path";
104
+ function buildTranspilers(plugins) {
105
+ const m = /* @__PURE__ */ new Map();
106
+ for (const plugin of plugins) {
107
+ plugin.transpilers?.forEach((t) => {
108
+ return m.set(t.extension, t);
109
+ });
110
+ }
111
+ return m;
112
+ }
113
+ function mogrifyPackageJsonImports(contents, transpilers) {
114
+ let parsed;
115
+ try {
116
+ parsed = JSON.parse(contents);
117
+ } catch {
118
+ return contents;
119
+ }
120
+ let ref;
121
+ if (!((ref = parsed.imports) != null && typeof ref === "object")) {
122
+ return contents;
123
+ }
124
+ let modified = false;
125
+ function recurse(node) {
126
+ if (!(node != null && typeof node === "object")) {
127
+ return;
128
+ }
129
+ const obj = node;
130
+ for (const key in obj) {
131
+ const value = obj[key];
132
+ if (typeof value === "string") {
133
+ const ext = getExtensionFromPath(value);
134
+ let ref1;
135
+ if ((ref1 = transpilers.get(ext)) != null) {
136
+ const t = ref1;
137
+ obj[key] = value + t.target;
138
+ modified = true;
139
+ }
140
+ } else if (value) {
141
+ recurse(value);
142
+ }
143
+ }
144
+ }
145
+ recurse(parsed.imports);
146
+ if (modified) {
147
+ return JSON.stringify(parsed);
148
+ } else return contents;
149
+ }
150
+ function parseTsConfigForCivet(projectPath, transpilers, options = {}) {
151
+ const widen = options.widenIncludeFilter ?? true;
152
+ const system = options.system ?? ts4.sys;
153
+ const extraExtensions = Array.from(transpilers.keys());
154
+ let ref2;
155
+ if (widen && extraExtensions.length > 0) {
156
+ ref2 = {
157
+ ...system,
158
+ readDirectory: function(p, extensions, excludes, includes, depth) {
159
+ const exts = extensions ? [...extensions, ...extraExtensions] : void 0;
160
+ return system.readDirectory(p, exts, excludes, includes, depth).map((f) => {
161
+ for (const ext of extraExtensions) {
162
+ if (f.endsWith(ext)) {
163
+ const t = transpilers.get(ext);
164
+ if (t) {
165
+ return f + t.target;
166
+ }
167
+ }
168
+ }
169
+ return f;
170
+ });
171
+ }
172
+ };
173
+ } else ref2 = system;
174
+ const configSys = ref2;
175
+ const tsConfigPath = path2.join(projectPath, "tsconfig.json");
176
+ const config = options.tsConfig ?? ts4.readConfigFile(tsConfigPath, system.readFile).config;
177
+ const parsed = ts4.parseJsonConfigFileContent(
178
+ config,
179
+ configSys,
180
+ projectPath,
181
+ {},
182
+ tsConfigPath,
183
+ void 0
184
+ );
185
+ parsed.options.allowNonTsExtensions ??= true;
186
+ parsed.options.jsx ??= ts4.JsxEmit.Preserve;
187
+ parsed.options.rootDir ??= projectPath;
188
+ return parsed;
189
+ }
190
+
191
+ // source/ts-service/host.civet
192
+ import assert from "node:assert";
193
+ var { isExternalModuleNameRelative } = ts5;
194
+ function TSHost(compilationSettings, initialFileNames, baseHost, transpilers, docFactory, _logger = console, libDir) {
195
+ const { rootDir } = compilationSettings;
196
+ assert(rootDir, "TSHost requires a rootDir in compilationSettings");
197
+ const scriptFileNames = /* @__PURE__ */ new Map();
198
+ for (const fileName of initialFileNames) {
199
+ const scriptFileName = getTranspiledPath(fileName);
200
+ scriptFileNames.set(getCanonicalFileName(scriptFileName), scriptFileName);
201
+ }
202
+ const fileMetaData = /* @__PURE__ */ new Map();
203
+ const pathMap = /* @__PURE__ */ new Map();
204
+ const snapshotMap = /* @__PURE__ */ new Map();
205
+ let projectVersion = 0;
206
+ const resolutionCache = ts5.createModuleResolutionCache(rootDir, (fileName) => fileName, compilationSettings);
207
+ const baseReadFile = baseHost.readFile.bind(baseHost);
208
+ const baseFileExists = baseHost.fileExists.bind(baseHost);
209
+ const baseDirectoryExists = baseHost.directoryExists?.bind(baseHost) ?? (() => false);
210
+ let self;
211
+ return self = Object.assign({}, baseHost, {
212
+ /** Mogrifies transpilable extensions inside `package.json#imports` on read. */
213
+ readFile(filename) {
214
+ const contents = getPathSource(filename);
215
+ if (contents && path3.basename(filename) === "package.json") {
216
+ return mogrifyPackageJsonImports(contents, transpilers);
217
+ }
218
+ return contents;
219
+ },
220
+ /** Treats synthetic `<src>.<target>` siblings as existing whenever the source does. */
221
+ fileExists(filename) {
222
+ return pathExists(filename) || syntheticTargetExists(filename);
223
+ },
224
+ /**
225
+ * LSP bundles its own lib copies under `<dist>/lib` (libDir set);
226
+ * other consumers fall through to TS's resolved-module lookup.
227
+ */
228
+ getDefaultLibFileName(options) {
229
+ if (libDir) {
230
+ return path3.join(libDir, ts5.getDefaultLibFileName(options));
231
+ }
232
+ return baseHost.getDefaultLibFileName(options);
233
+ },
234
+ getDefaultLibLocation() {
235
+ if (libDir) {
236
+ return libDir;
237
+ }
238
+ return baseHost.getDefaultLibLocation?.() ?? path3.dirname(baseHost.getDefaultLibFileName(compilationSettings));
239
+ },
240
+ getModuleResolutionCache() {
241
+ return resolutionCache;
242
+ },
243
+ /**
244
+ * Defer to TS's standard resolver first; fall back to our own walk
245
+ * (paths / baseUrl / relative) for transpilable extensions TS doesn't
246
+ * know about. Requires `allowNonTsExtensions`; matches resolve to a
247
+ * synthetic `<src>.<target>` so subsequent `getScriptSnapshot` calls
248
+ * hit the transpiler.
249
+ */
250
+ resolveModuleNames(moduleNames, containingFile, _reusedNames, _redirectedReference, compilerOptions, _containingSourceFile) {
251
+ return moduleNames.map((name) => {
252
+ const { resolvedModule } = ts5.resolveModuleName(name, containingFile, compilerOptions, self, resolutionCache);
253
+ if (resolvedModule) {
254
+ return resolvedModule;
255
+ }
256
+ const extension = getExtensionFromPath(name);
257
+ let transpiler = transpilers.get(extension);
258
+ if (transpiler || !extension) {
259
+ const exists = transpiler ? pathExists : baseDirectoryExists;
260
+ const resolvedModule2 = (resolved2) => {
261
+ if (!transpiler) {
262
+ for (const [_, t] of transpilers) {
263
+ const index = path3.join(resolved2, "index" + t.extension);
264
+ if (pathExists(index)) {
265
+ transpiler = t;
266
+ resolved2 = index;
267
+ break;
268
+ }
269
+ }
270
+ if (!transpiler) {
271
+ return;
272
+ }
273
+ }
274
+ const { target } = transpiler;
275
+ return {
276
+ resolvedFileName: resolved2 + target,
277
+ extension: target,
278
+ isExternalLibraryImport: false
279
+ };
280
+ };
281
+ const { paths, pathsBasePath } = compilationSettings;
282
+ const baseUrl = compilationSettings.baseUrl;
283
+ if (!isExternalModuleNameRelative(name)) {
284
+ if (paths) {
285
+ const pathsBase = baseUrl ?? pathsBasePath;
286
+ let best = "";
287
+ let bestPrefix = "";
288
+ for (const [pattern, replacements] of Object.entries(paths)) {
289
+ if (pattern.endsWith("*")) {
290
+ const prefix = pattern.slice(0, -1);
291
+ if (name.startsWith(prefix)) {
292
+ for (const replacement of replacements) {
293
+ const resolved2 = path3.resolve(
294
+ pathsBase,
295
+ replacement.replace("*", name.slice(prefix.length))
296
+ );
297
+ if (exists(resolved2) && prefix.length > bestPrefix.length) {
298
+ best = resolved2;
299
+ bestPrefix = prefix;
300
+ }
301
+ }
302
+ }
303
+ } else if (name === pattern) {
304
+ for (const replacement of replacements) {
305
+ const resolved2 = path3.resolve(pathsBase, replacement);
306
+ if (exists(resolved2) && pattern.length > bestPrefix.length) {
307
+ best = resolved2;
308
+ bestPrefix = pattern;
309
+ }
310
+ }
311
+ }
312
+ }
313
+ if (best) {
314
+ return resolvedModule2(best);
315
+ }
316
+ }
317
+ if (baseUrl) {
318
+ const resolved2 = path3.resolve(baseUrl, name);
319
+ if (exists(resolved2)) {
320
+ return resolvedModule2(resolved2);
321
+ }
322
+ }
323
+ } else {
324
+ }
325
+ const resolved = path3.resolve(path3.dirname(containingFile), name);
326
+ if (exists(resolved)) {
327
+ return resolvedModule2(resolved);
328
+ }
329
+ }
330
+ return void 0;
331
+ });
332
+ },
333
+ resolveModuleNameLiterals(literals, containingFile, _redirectedReference, compilerOptions) {
334
+ return literals.map((literal) => {
335
+ const name = literal.text;
336
+ for (const [ext, t] of transpilers) {
337
+ if (name.endsWith(ext)) {
338
+ const resolved = path3.resolve(path3.dirname(containingFile), name);
339
+ if (pathExists(resolved)) {
340
+ return {
341
+ resolvedModule: {
342
+ resolvedFileName: resolved + t.target,
343
+ extension: t.target,
344
+ isExternalLibraryImport: false
345
+ }
346
+ };
347
+ }
348
+ }
349
+ }
350
+ if (!getExtensionFromPath(name)) {
351
+ const resolved = path3.resolve(path3.dirname(containingFile), name);
352
+ if (baseDirectoryExists(resolved)) {
353
+ for (const [_, t] of transpilers) {
354
+ const index = path3.join(resolved, "index" + t.extension);
355
+ if (pathExists(index)) {
356
+ return {
357
+ resolvedModule: {
358
+ resolvedFileName: index + t.target,
359
+ extension: t.target,
360
+ isExternalLibraryImport: false
361
+ }
362
+ };
363
+ }
364
+ }
365
+ }
366
+ }
367
+ return { resolvedModule: ts5.resolveModuleName(name, containingFile, compilerOptions, self, resolutionCache).resolvedModule };
368
+ });
369
+ },
370
+ addOrUpdateDocument(doc) {
371
+ const rawPath = path3.normalize(docFactory.uriToPath(doc.uri));
372
+ const p = getCanonicalFileName(rawPath);
373
+ snapshotMap.delete(p);
374
+ projectVersion++;
375
+ const extension = getExtensionFromPath(p);
376
+ const transpiler = transpilers.get(extension);
377
+ if (transpiler) {
378
+ const { target } = transpiler;
379
+ const transpiledPath = p + target;
380
+ const displayTranspiledPath = rawPath + target;
381
+ let transpiledDoc = pathMap.get(transpiledPath);
382
+ if (!transpiledDoc) {
383
+ initTranspiledDoc(displayTranspiledPath);
384
+ }
385
+ snapshotMap.delete(transpiledPath);
386
+ pathMap.set(p, doc);
387
+ return;
388
+ }
389
+ scriptFileNames.set(p, rawPath);
390
+ pathMap.set(p, doc);
391
+ },
392
+ addScriptFileName(p) {
393
+ const target = getTranspiledPath(p);
394
+ const canonical = getCanonicalFileName(target);
395
+ if (scriptFileNames.has(canonical)) {
396
+ return;
397
+ }
398
+ scriptFileNames.set(canonical, target);
399
+ projectVersion++;
400
+ },
401
+ closeDocument(rawPath) {
402
+ const canonical = getCanonicalFileName(rawPath);
403
+ const transpiledPath = getCanonicalTranspiledPath(rawPath);
404
+ pathMap.delete(canonical);
405
+ snapshotMap.delete(canonical);
406
+ fileMetaData.delete(canonical);
407
+ if (transpiledPath !== canonical) {
408
+ pathMap.delete(transpiledPath);
409
+ snapshotMap.delete(transpiledPath);
410
+ }
411
+ projectVersion++;
412
+ },
413
+ removeDocument(rawPath) {
414
+ const canonical = getCanonicalFileName(rawPath);
415
+ const transpiledPath = getCanonicalTranspiledPath(rawPath);
416
+ pathMap.delete(canonical);
417
+ snapshotMap.delete(canonical);
418
+ fileMetaData.delete(canonical);
419
+ scriptFileNames.delete(canonical);
420
+ if (transpiledPath !== canonical) {
421
+ pathMap.delete(transpiledPath);
422
+ snapshotMap.delete(transpiledPath);
423
+ scriptFileNames.delete(transpiledPath);
424
+ }
425
+ projectVersion++;
426
+ },
427
+ getMeta(p) {
428
+ p = getCanonicalFileName(p);
429
+ getOrCreatePathSnapshot(getCanonicalTranspiledPath(p));
430
+ return fileMetaData.get(p);
431
+ },
432
+ getProjectVersion() {
433
+ return projectVersion.toString();
434
+ },
435
+ getCompilationSettings() {
436
+ return compilationSettings;
437
+ },
438
+ // TS passes forward-slash paths on every OS; both methods
439
+ // normalize through getCanonicalFileName before lookup.
440
+ getScriptSnapshot(p) {
441
+ return getOrCreatePathSnapshot(getCanonicalFileName(p));
442
+ },
443
+ getScriptVersion(p) {
444
+ return pathMap.get(getCanonicalFileName(p))?.version.toString() || "0";
445
+ },
446
+ getScriptFileNames() {
447
+ return Array.from(scriptFileNames.values());
448
+ },
449
+ // CompilerHost requires writeFile, but our consumers always pass an
450
+ // explicit writeFile to program.emit() / builder.emit(), so this is
451
+ // unreachable — keep as a no-op to satisfy the interface.
452
+ writeFile(_fileName, _content) {
453
+ return;
454
+ }
455
+ });
456
+ function syntheticTargetExists(filename) {
457
+ for (const [ext, t] of transpilers) {
458
+ if (filename.endsWith(t.target)) {
459
+ const source = filename.slice(0, -t.target.length);
460
+ if (source.endsWith(ext) && pathExists(source)) {
461
+ return true;
462
+ }
463
+ }
464
+ }
465
+ return false;
466
+ }
467
+ function pathExists(p) {
468
+ return pathMap.has(getCanonicalFileName(p)) || baseFileExists(p);
469
+ }
470
+ function getPathSource(p) {
471
+ p = getCanonicalFileName(p);
472
+ const doc = pathMap.get(p);
473
+ if (doc) {
474
+ return doc.getText();
475
+ }
476
+ if (baseFileExists(p)) {
477
+ return baseReadFile(p);
478
+ }
479
+ return void 0;
480
+ }
481
+ function getTranspiledPath(p) {
482
+ p = path3.normalize(p);
483
+ const extension = getExtensionFromPath(p);
484
+ const transpiler = transpilers.get(extension);
485
+ if (transpiler) {
486
+ return p + transpiler.target;
487
+ }
488
+ return p;
489
+ }
490
+ function getCanonicalTranspiledPath(p) {
491
+ return getCanonicalFileName(getTranspiledPath(p));
492
+ }
493
+ function getOrCreatePathSnapshot(p) {
494
+ const rawPath = path3.normalize(p);
495
+ p = getCanonicalFileName(rawPath);
496
+ let snapshot = snapshotMap.get(p);
497
+ if (snapshot) {
498
+ return snapshot;
499
+ }
500
+ let transpiler;
501
+ const exts = getTranspiledExtensionsFromPath(p);
502
+ if (exts && (transpiler = transpilers.get(exts[0]))) {
503
+ const sourcePath = removeExtension(p);
504
+ const sourceDoc = pathMap.get(sourcePath);
505
+ let transpiledDoc = pathMap.get(p);
506
+ if (!transpiledDoc) {
507
+ transpiledDoc = initTranspiledDoc(rawPath);
508
+ }
509
+ let source;
510
+ let sourceDocVersion = 0;
511
+ if (!sourceDoc) {
512
+ source = getPathSource(sourcePath);
513
+ } else {
514
+ source = sourceDoc.getText();
515
+ sourceDocVersion = sourceDoc.version;
516
+ }
517
+ if (source && sourceDocVersion > transpiledDoc.version) {
518
+ const transpiledCode = doTranspileAndUpdateMeta(transpiledDoc, sourceDocVersion, transpiler, sourcePath, source);
519
+ if (transpiledCode != null) {
520
+ snapshot = Snap(transpiledCode);
521
+ }
522
+ }
523
+ if (!snapshot) {
524
+ snapshot = Snap(transpiledDoc.getText());
525
+ }
526
+ snapshotMap.set(p, snapshot);
527
+ return snapshot;
528
+ }
529
+ snapshot = Snap(getPathSource(p) ?? "");
530
+ snapshotMap.set(p, snapshot);
531
+ return snapshot;
532
+ }
533
+ function createOrUpdateMeta(p, update) {
534
+ p = getCanonicalFileName(p);
535
+ let meta = fileMetaData.get(p);
536
+ if (!meta) {
537
+ return fileMetaData.set(p, update);
538
+ } else {
539
+ return Object.assign(meta, update);
540
+ }
541
+ }
542
+ function doTranspileAndUpdateMeta(transpiledDoc, version, transpiler, sourcePath, sourceCode) {
543
+ let result;
544
+ try {
545
+ result = transpiler.compile(sourcePath, sourceCode);
546
+ } catch (e) {
547
+ createOrUpdateMeta(sourcePath, {
548
+ transpiledDoc,
549
+ sourcemapLines: void 0,
550
+ commentRanges: void 0,
551
+ parseErrors: [e],
552
+ fatal: true
553
+ });
554
+ return;
555
+ }
556
+ if (result instanceof Promise) {
557
+ return;
558
+ }
559
+ if (!result) {
560
+ return;
561
+ }
562
+ const { code: transpiledCode, sourceMap, commentRanges, errors } = result;
563
+ let sourcemapLines = sourceMap?.lines;
564
+ sourcemapLines ??= sourceMap?.data?.lines;
565
+ createOrUpdateMeta(sourcePath, {
566
+ transpiledDoc,
567
+ sourcemapLines,
568
+ commentRanges,
569
+ parseErrors: errors,
570
+ fatal: false
571
+ });
572
+ docFactory.update(transpiledDoc, transpiledCode, version);
573
+ return transpiledCode;
574
+ }
575
+ function initTranspiledDoc(p) {
576
+ const scriptPath = path3.normalize(p);
577
+ p = getCanonicalFileName(scriptPath);
578
+ const uri = docFactory.pathToUri(scriptPath);
579
+ const transpiledDoc = docFactory.create(uri, "none", -1, "");
580
+ pathMap.set(p, transpiledDoc);
581
+ scriptFileNames.set(p, scriptPath);
582
+ return transpiledDoc;
583
+ }
584
+ }
585
+
586
+ // source/ts-service/service.civet
587
+ import path4 from "node:path";
588
+ import ts6 from "typescript";
589
+ import {} from "typescript";
590
+ var {
591
+ createCompilerHost,
592
+ createLanguageService
593
+ } = ts6;
594
+ function TSService(projectPath, options) {
595
+ const { plugins = [], docFactory, libDir, discoverProjectFiles = true, extraCompilerOptions } = options;
596
+ const system = options.system ?? ts6.sys;
597
+ const logger = options.logger ?? console;
598
+ const transpilers = buildTranspilers(plugins);
599
+ function registerPlugin(plugin) {
600
+ plugin.transpilers?.forEach((t) => {
601
+ return transpilers.set(t.extension, t);
602
+ });
603
+ }
604
+ const parsedConfig = parseTsConfigForCivet(projectPath, transpilers, {
605
+ tsConfig: options.tsConfig,
606
+ widenIncludeFilter: discoverProjectFiles,
607
+ system
608
+ });
609
+ let ref;
610
+ if (extraCompilerOptions) {
611
+ ref = { ...parsedConfig.options, ...extraCompilerOptions };
612
+ } else {
613
+ ref = parsedConfig.options;
614
+ }
615
+ ;
616
+ const hostOptions = ref;
617
+ const baseHost = createBaseHost(hostOptions, system);
618
+ const host = TSHost(hostOptions, parsedConfig.fileNames, baseHost, transpilers, docFactory, logger, libDir);
619
+ const service = createLanguageService(host);
620
+ const loadPlugins = async function() {
621
+ const civetFolder = path4.join(projectPath, "./.civet/");
622
+ let civetFiles;
623
+ try {
624
+ civetFiles = system.readDirectory(civetFolder);
625
+ } catch (e) {
626
+ logger.info(`No .civet plugin folder at ${civetFolder} (${e.message})`);
627
+ return;
628
+ }
629
+ const pluginFiles = civetFiles.filter((file) => file.endsWith("plugin.mjs"));
630
+ for (const filePath of pluginFiles) {
631
+ const pluginUri = docFactory.pathToUri(filePath);
632
+ logger.info("Loading plugin " + pluginUri);
633
+ try {
634
+ const { default: plugin } = await import(
635
+ /* @vite-ignore */
636
+ pluginUri
637
+ );
638
+ logger.info("Loaded plugin " + plugin);
639
+ registerPlugin(plugin);
640
+ } catch (e) {
641
+ logger.error("Error loading plugin " + pluginUri + " " + e);
642
+ }
643
+ }
644
+ return;
645
+ };
646
+ return Object.assign({}, service, {
647
+ host,
648
+ /** `foo.civet.tsx` → `foo.civet`; passthrough for non-transpiled files. */
649
+ getSourceFileName(fileName) {
650
+ return getCanonicalFileName(remapFileName(fileName, transpilers));
651
+ },
652
+ registerPlugin,
653
+ loadPlugins
654
+ });
655
+ }
656
+ function createBaseHost(options, system) {
657
+ if (system === ts6.sys) {
658
+ return createCompilerHost(options);
659
+ }
660
+ const getCanonicalFileName2 = (fileName) => {
661
+ if (system.useCaseSensitiveFileNames) {
662
+ return fileName;
663
+ } else return fileName.toLowerCase();
664
+ };
665
+ return {
666
+ getSourceFile(fileName, languageVersion) {
667
+ const sourceText = system.readFile(fileName);
668
+ if (!(sourceText != null)) {
669
+ return;
670
+ }
671
+ return ts6.createSourceFile(fileName, sourceText, languageVersion);
672
+ },
673
+ getDefaultLibFileName(options2) {
674
+ return path4.join("/typescript/lib", ts6.getDefaultLibFileName(options2));
675
+ },
676
+ writeFile(fileName, content) {
677
+ return system.writeFile?.(fileName, content);
678
+ },
679
+ getCurrentDirectory() {
680
+ return system.getCurrentDirectory();
681
+ },
682
+ getDirectories(path7) {
683
+ return system.getDirectories?.(path7) ?? [];
684
+ },
685
+ fileExists(fileName) {
686
+ return system.fileExists(fileName);
687
+ },
688
+ readFile(fileName) {
689
+ return system.readFile(fileName);
690
+ },
691
+ useCaseSensitiveFileNames() {
692
+ return system.useCaseSensitiveFileNames;
693
+ },
694
+ getCanonicalFileName: getCanonicalFileName2,
695
+ getNewLine() {
696
+ return system.newLine;
697
+ },
698
+ directoryExists(path7) {
699
+ return system.directoryExists?.(path7) ?? false;
700
+ },
701
+ readDirectory(path7, extensions, excludes, includes, depth) {
702
+ return system.readDirectory(path7, extensions, excludes, includes, depth);
703
+ },
704
+ realpath(path7) {
705
+ return system.realpath ? system.realpath(path7) : path7;
706
+ }
707
+ };
708
+ }
709
+
710
+ // source/ts-service/doc.civet
711
+ import { pathToFileURL, fileURLToPath } from "node:url";
712
+ var InMemoryDoc = class {
713
+ uri;
714
+ version;
715
+ text;
716
+ constructor(uri, version, text) {
717
+ this.uri = uri;
718
+ this.version = version;
719
+ this.text = text;
720
+ }
721
+ getText() {
722
+ return this.text;
723
+ }
724
+ setText(t) {
725
+ this.text = t;
726
+ }
727
+ };
728
+ function createInMemoryDocFactory() {
729
+ return {
730
+ create: (uri, _languageId, version, text) => {
731
+ return new InMemoryDoc(uri, version, text);
732
+ },
733
+ update: (doc, text, version) => {
734
+ doc.setText(text);
735
+ return doc.version = version;
736
+ },
737
+ uriToPath: (uri) => fileURLToPath(uri),
738
+ pathToUri: (p) => pathToFileURL(p).toString()
739
+ };
740
+ }
741
+
742
+ // source/ts-service/plugins/civet.civet
743
+ import { lib as BundledCivetLib } from "@danielx/civet";
744
+ import BundledCivetModule from "@danielx/civet";
745
+ import BundledCivetPackage from "@danielx/civet/package.json" with { type: "json" };
746
+ import {} from "typescript";
747
+
748
+ // source/cache.civet
749
+ import * as crypto from "node:crypto";
750
+ import * as fs from "node:fs";
751
+ import * as path5 from "node:path";
752
+ function hashParts(parts) {
753
+ const hash = crypto.createHash("sha1");
754
+ for (const part of parts) {
755
+ hash.update(part).update("\0");
756
+ }
757
+ return hash.digest("hex");
758
+ }
759
+ function stableStringify(value) {
760
+ return JSON.stringify(value, (_key, val) => {
761
+ if (typeof val === "function") {
762
+ return void 0;
763
+ }
764
+ if (val && typeof val === "object" && !Array.isArray(val)) {
765
+ const sorted = {};
766
+ for (const key of Object.keys(val).sort()) {
767
+ sorted[key] = val[key];
768
+ }
769
+ return sorted;
770
+ }
771
+ return val;
772
+ });
773
+ }
774
+ function makeCacheKey(input) {
775
+ const resolved = path5.resolve(input.sourcePath).replace(/\\/g, "/");
776
+ return hashParts([
777
+ input.source,
778
+ input.compilerName,
779
+ input.compilerVersion,
780
+ input.civetVersion ?? "",
781
+ input.civetMtime ?? "",
782
+ resolved,
783
+ stableStringify(input.options ?? {})
784
+ ]);
785
+ }
786
+ function createMemoryCache() {
787
+ const store = /* @__PURE__ */ new Map();
788
+ return {
789
+ get(key) {
790
+ return store.get(key);
791
+ },
792
+ set(key, value) {
793
+ store.set(key, value);
794
+ return;
795
+ }
796
+ };
797
+ }
798
+ function createDiskCache(dir) {
799
+ try {
800
+ fs.mkdirSync(dir, { recursive: true });
801
+ } catch {
802
+ }
803
+ return {
804
+ get(key) {
805
+ const target = path5.join(dir, key);
806
+ try {
807
+ const content = fs.readFileSync(target, "utf8");
808
+ try {
809
+ const now = /* @__PURE__ */ new Date();
810
+ fs.utimesSync(target, now, now);
811
+ } catch {
812
+ }
813
+ return content;
814
+ } catch {
815
+ return void 0;
816
+ }
817
+ },
818
+ set(key, value) {
819
+ const target = path5.join(dir, key);
820
+ try {
821
+ const tmp = `${target}.tmp.${process.pid}`;
822
+ fs.writeFileSync(tmp, value);
823
+ return fs.renameSync(tmp, target);
824
+ } catch {
825
+ return;
826
+ }
827
+ }
828
+ };
829
+ }
830
+
831
+ // source/ts-service/plugins/civet.civet
832
+ function makeCivetPlugin(options = {}) {
833
+ const Civet = options.Civet ?? BundledCivetModule;
834
+ const CivetLib = options.CivetLib ?? BundledCivetLib;
835
+ const CivetVersion = options.CivetVersion ?? BundledCivetPackage.version;
836
+ const civetConfig = options.config ?? {};
837
+ const cache = options.cache;
838
+ function transpileCivet(p, source) {
839
+ const errors = [];
840
+ const options2 = {
841
+ ...civetConfig,
842
+ filename: p,
843
+ errors,
844
+ sync: true,
845
+ parseOptions: {
846
+ ...civetConfig.parseOptions,
847
+ comptime: false
848
+ }
849
+ };
850
+ const [major, minor, patch] = CivetVersion.split(".").map(Number);
851
+ if (major === 0 && (minor < 9 || minor === 9 && patch < 4)) {
852
+ const result = Civet.compile(source, { ...options2, sourceMap: true });
853
+ return { ...result, errors };
854
+ }
855
+ let ref;
856
+ if (cache) {
857
+ ref = makeCacheKey({
858
+ source,
859
+ sourcePath: p,
860
+ compilerName: "civet",
861
+ compilerVersion: CivetVersion,
862
+ options: civetConfig
863
+ });
864
+ } else ref = void 0;
865
+ const cacheKey = ref;
866
+ if (cacheKey) {
867
+ const hit = cache.get(cacheKey);
868
+ if (hit) {
869
+ try {
870
+ const parsed = JSON.parse(hit);
871
+ const result = {
872
+ code: parsed.code,
873
+ sourceMap: { lines: parsed.lines },
874
+ errors
875
+ };
876
+ if (parsed.commentRanges) {
877
+ result.commentRanges = parsed.commentRanges;
878
+ }
879
+ return result;
880
+ } catch {
881
+ }
882
+ }
883
+ }
884
+ options2.ast = true;
885
+ const ast = Civet.compile(source, options2);
886
+ const sourceMap = new Civet.SourceMap(source, p);
887
+ const code = Civet.generate(ast, {
888
+ ...options2,
889
+ sourceMap
890
+ });
891
+ const commentRanges = collectCommentRanges(ast);
892
+ if (cacheKey && errors.length === 0) {
893
+ const lines = sourceMap.lines ?? sourceMap.data?.lines;
894
+ cache.set(cacheKey, JSON.stringify({ code, lines, commentRanges }));
895
+ }
896
+ return {
897
+ code,
898
+ sourceMap,
899
+ commentRanges,
900
+ errors
901
+ };
902
+ }
903
+ function collectCommentRanges(ast) {
904
+ const comments = CivetLib.gatherRecursiveAll(
905
+ ast,
906
+ (node) => {
907
+ return node?.type === "Comment" && node.$loc?.length > 0;
908
+ }
909
+ );
910
+ return comments.map((comment) => comment.$loc);
911
+ }
912
+ return {
913
+ transpilers: [{
914
+ extension: ".civet",
915
+ target: ".tsx",
916
+ compile: transpileCivet
917
+ }]
918
+ };
919
+ }
920
+
921
+ // source/ts-service/plugins/hera.civet
922
+ import {} from "@danielx/civet";
923
+ import BundledCivetModule2 from "@danielx/civet";
924
+ import BundledCivetPackage2 from "@danielx/civet/package.json" with { type: "json" };
925
+ import { createRequire } from "node:module";
926
+ import {} from "typescript";
927
+ var heraRequire = createRequire(
928
+ /* c8 ignore start -- one branch fires per build target; tests cover only one */
929
+ typeof __filename !== "undefined" ? __filename : import.meta.url
930
+ /* c8 ignore stop */
931
+ );
932
+ function makeHeraPlugin(options = {}) {
933
+ const Civet = options.Civet ?? BundledCivetModule2;
934
+ const CivetVersion = options.CivetVersion ?? BundledCivetPackage2.version;
935
+ const civetConfig = options.config ?? {};
936
+ const cache = options.cache;
937
+ let resolvedHera;
938
+ let resolvedHeraVersion;
939
+ function getHera() {
940
+ if (resolvedHera) {
941
+ return resolvedHera;
942
+ }
943
+ if (options.Hera) {
944
+ resolvedHera = options.Hera;
945
+ return resolvedHera;
946
+ }
947
+ let mod;
948
+ try {
949
+ mod = heraRequire("@danielx/hera");
950
+ } catch {
951
+ throw new Error("@danielx/hera is not installed; install it as a (peer) dependency to type-check .hera files, or pass HeraPluginOptions.Hera explicitly.");
952
+ }
953
+ resolvedHera = { compile: mod.compile };
954
+ return resolvedHera;
955
+ }
956
+ function getHeraVersion() {
957
+ if (resolvedHeraVersion) {
958
+ return resolvedHeraVersion;
959
+ }
960
+ if (options.HeraVersion) {
961
+ resolvedHeraVersion = options.HeraVersion;
962
+ return resolvedHeraVersion;
963
+ }
964
+ try {
965
+ const pkg = heraRequire("@danielx/hera/package.json");
966
+ resolvedHeraVersion = pkg.version;
967
+ } catch {
968
+ resolvedHeraVersion = "unknown";
969
+ }
970
+ return resolvedHeraVersion;
971
+ }
972
+ const heraOptions = {
973
+ module: true,
974
+ sourceMap: true,
975
+ language: "civet"
976
+ };
977
+ function transpileHera(p, source) {
978
+ const errors = [];
979
+ let ref;
980
+ if (cache) {
981
+ ref = makeCacheKey({
982
+ source,
983
+ sourcePath: p,
984
+ compilerName: "hera",
985
+ compilerVersion: getHeraVersion(),
986
+ civetVersion: CivetVersion,
987
+ options: { heraOptions, civetConfig }
988
+ });
989
+ } else ref = void 0;
990
+ const cacheKey = ref;
991
+ if (cacheKey) {
992
+ const hit = cache.get(cacheKey);
993
+ if (hit) {
994
+ try {
995
+ const { code, lines } = JSON.parse(hit);
996
+ return {
997
+ code,
998
+ sourceMap: { lines },
999
+ errors
1000
+ };
1001
+ } catch {
1002
+ }
1003
+ }
1004
+ }
1005
+ try {
1006
+ const heraResult = getHera().compile(source, { ...heraOptions, filename: p });
1007
+ const civetOptions = {
1008
+ ...civetConfig,
1009
+ filename: p,
1010
+ js: false,
1011
+ sync: true,
1012
+ sourceMap: true,
1013
+ upstreamSourceMap: heraResult.sourceMap,
1014
+ parseOptions: {
1015
+ ...civetConfig.parseOptions,
1016
+ comptime: false
1017
+ }
1018
+ };
1019
+ const civetResult = Civet.compile(heraResult.code, civetOptions);
1020
+ if (cacheKey) {
1021
+ const sm = civetResult.sourceMap;
1022
+ const lines = sm?.lines ?? sm?.data?.lines;
1023
+ cache.set(cacheKey, JSON.stringify({ code: civetResult.code, lines }));
1024
+ }
1025
+ return {
1026
+ code: civetResult.code,
1027
+ sourceMap: civetResult.sourceMap,
1028
+ errors
1029
+ };
1030
+ } catch (e) {
1031
+ errors.push(e);
1032
+ return { code: "", errors };
1033
+ }
1034
+ }
1035
+ return {
1036
+ transpilers: [{
1037
+ extension: ".hera",
1038
+ target: ".tsx",
1039
+ compile: transpileHera
1040
+ }]
1041
+ };
1042
+ }
1043
+
1044
+ // source/ts-service/typecheck.civet
1045
+ import ts7 from "typescript";
1046
+ import * as fs2 from "fs";
1047
+ import * as path6 from "path";
1048
+ function makeIncrementalTypecheckProgram(projectPath, options) {
1049
+ const transpilers = buildTranspilers(options.plugins);
1050
+ const extraExtensions = Array.from(transpilers.keys());
1051
+ const parsed = parseTsConfigForCivet(projectPath, transpilers, { tsConfig: options.tsConfig });
1052
+ const compilerOptions = {
1053
+ ...parsed.options,
1054
+ ...options.extraCompilerOptions
1055
+ };
1056
+ compilerOptions.jsx ??= ts7.JsxEmit.Preserve;
1057
+ const baseHost = ts7.createIncrementalCompilerHost(compilerOptions);
1058
+ const fileMetaData = /* @__PURE__ */ new Map();
1059
+ const hashText = (text) => {
1060
+ return baseHost.createHash?.(text) ?? text.length.toString();
1061
+ };
1062
+ const origGetSourceFile = baseHost.getSourceFile.bind(baseHost);
1063
+ baseHost.getSourceFile = (fileName, langVersion, onError, shouldCreateNew) => {
1064
+ const exts = getTranspiledExtensionsFromPath(fileName);
1065
+ const transpiler = exts && transpilers.get(exts[0]);
1066
+ if (exts && transpiler && transpiler.target === exts[1]) {
1067
+ const sourcePath = removeExtension(fileName);
1068
+ let sourceText;
1069
+ try {
1070
+ sourceText = fs2.readFileSync(sourcePath, "utf8");
1071
+ } catch {
1072
+ return void 0;
1073
+ }
1074
+ let result;
1075
+ try {
1076
+ result = transpiler.compile(sourcePath, sourceText);
1077
+ } catch (e) {
1078
+ fileMetaData.set(getCanonicalFileName(sourcePath), {
1079
+ sourcemapLines: void 0,
1080
+ transpiledDoc: void 0,
1081
+ commentRanges: void 0,
1082
+ parseErrors: [e],
1083
+ fatal: true
1084
+ });
1085
+ return void 0;
1086
+ }
1087
+ if (result instanceof Promise) {
1088
+ return void 0;
1089
+ }
1090
+ if (!(result && result.code)) {
1091
+ return void 0;
1092
+ }
1093
+ const sourcemapLines = result.sourceMap?.lines ?? result.sourceMap?.data?.lines;
1094
+ fileMetaData.set(getCanonicalFileName(sourcePath), {
1095
+ sourcemapLines,
1096
+ transpiledDoc: void 0,
1097
+ commentRanges: result.commentRanges,
1098
+ parseErrors: result.errors,
1099
+ fatal: false
1100
+ });
1101
+ const sf2 = ts7.createSourceFile(fileName, result.code, langVersion, true);
1102
+ sf2.version = hashText(result.code);
1103
+ return sf2;
1104
+ }
1105
+ const sf = origGetSourceFile(fileName, langVersion, onError, shouldCreateNew);
1106
+ if (sf && sf.version === void 0) {
1107
+ sf.version = hashText(sf.text);
1108
+ }
1109
+ return sf;
1110
+ };
1111
+ const origFileExists = baseHost.fileExists.bind(baseHost);
1112
+ baseHost.fileExists = (fileName) => {
1113
+ const exts = getTranspiledExtensionsFromPath(fileName);
1114
+ if (exts) {
1115
+ const transpiler = transpilers.get(exts[0]);
1116
+ if (transpiler && transpiler.target === exts[1]) {
1117
+ return origFileExists(removeExtension(fileName));
1118
+ }
1119
+ }
1120
+ return origFileExists(fileName);
1121
+ };
1122
+ const origReadFile = baseHost.readFile.bind(baseHost);
1123
+ baseHost.readFile = (fileName) => {
1124
+ const contents = origReadFile(fileName);
1125
+ if (contents && path6.basename(fileName) === "package.json") {
1126
+ return mogrifyPackageJsonImports(contents, transpilers);
1127
+ }
1128
+ return contents;
1129
+ };
1130
+ baseHost.resolveModuleNameLiterals = (literals, containingFile, _redirected, opts) => {
1131
+ return literals.map((lit) => {
1132
+ const name = lit.text;
1133
+ for (const ext of extraExtensions) {
1134
+ if (name.endsWith(ext)) {
1135
+ const t = transpilers.get(ext);
1136
+ const containingDir = path6.dirname(containingFile);
1137
+ const resolved = path6.resolve(containingDir, name);
1138
+ if (origFileExists(resolved)) {
1139
+ return {
1140
+ resolvedModule: {
1141
+ resolvedFileName: resolved + t.target,
1142
+ extension: t.target,
1143
+ isExternalLibraryImport: false
1144
+ }
1145
+ };
1146
+ }
1147
+ }
1148
+ }
1149
+ return { resolvedModule: ts7.resolveModuleName(name, containingFile, opts, baseHost).resolvedModule };
1150
+ });
1151
+ };
1152
+ const programOptions = {
1153
+ rootNames: parsed.fileNames,
1154
+ options: compilerOptions,
1155
+ host: baseHost,
1156
+ configFileParsingDiagnostics: ts7.getConfigFileParsingDiagnostics(parsed)
1157
+ };
1158
+ if (parsed.projectReferences) {
1159
+ programOptions.projectReferences = parsed.projectReferences;
1160
+ }
1161
+ const builder = ts7.createIncrementalProgram(programOptions);
1162
+ return {
1163
+ builder,
1164
+ host: baseHost,
1165
+ getMeta(sourcePath) {
1166
+ return fileMetaData.get(getCanonicalFileName(sourcePath));
1167
+ },
1168
+ configErrors: parsed.errors
1169
+ };
1170
+ }
1171
+ export {
1172
+ Snap,
1173
+ TSHost,
1174
+ TSService,
1175
+ createDiskCache,
1176
+ createInMemoryDocFactory,
1177
+ createMemoryCache,
1178
+ fullDiffTextChangeRange,
1179
+ getCanonicalFileName,
1180
+ getExtensionFromPath,
1181
+ getTranspiledExtensionsFromPath,
1182
+ makeCivetPlugin,
1183
+ makeHeraPlugin,
1184
+ makeIncrementalTypecheckProgram,
1185
+ remapFileName,
1186
+ removeExtension
1187
+ };
1188
+ //# sourceMappingURL=index.mjs.map