truecourse 0.1.13 → 0.1.15
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/cli.mjs +153 -76
- package/package.json +4 -4
- package/public/assets/{index-CVwZeppe.js → index-DMFqQ7fW.js} +63 -63
- package/public/index.html +2 -2
- package/server.mjs +258 -94
- package/skills/truecourse/truecourse-analyze/SKILL.md +39 -0
- package/skills/truecourse/truecourse-fix/SKILL.md +34 -0
- package/skills/truecourse/truecourse-list/SKILL.md +26 -0
package/cli.mjs
CHANGED
|
@@ -12271,6 +12271,9 @@ var init_macos = __esm({
|
|
|
12271
12271
|
async install(serverPath, logPath) {
|
|
12272
12272
|
const envFile = path.join(os.homedir(), ".truecourse", ".env");
|
|
12273
12273
|
const envVars = parseEnvFile(envFile);
|
|
12274
|
+
if (process.env.PATH && !envVars.PATH) {
|
|
12275
|
+
envVars.PATH = process.env.PATH;
|
|
12276
|
+
}
|
|
12274
12277
|
fs2.mkdirSync(PLIST_DIR, { recursive: true });
|
|
12275
12278
|
fs2.mkdirSync(path.dirname(logPath), { recursive: true });
|
|
12276
12279
|
const plist = buildPlist(serverPath, logPath, envVars);
|
|
@@ -12610,6 +12613,7 @@ var init_logs = __esm({
|
|
|
12610
12613
|
// tools/cli/src/commands/start.ts
|
|
12611
12614
|
var start_exports = {};
|
|
12612
12615
|
__export(start_exports, {
|
|
12616
|
+
getServerProcess: () => getServerProcess,
|
|
12613
12617
|
runStart: () => runStart
|
|
12614
12618
|
});
|
|
12615
12619
|
import { spawn as spawn2 } from "node:child_process";
|
|
@@ -12620,7 +12624,7 @@ function getServerPath() {
|
|
|
12620
12624
|
}
|
|
12621
12625
|
async function healthcheck() {
|
|
12622
12626
|
const url2 = getServerUrl();
|
|
12623
|
-
for (let i = 0; i <
|
|
12627
|
+
for (let i = 0; i < 120; i++) {
|
|
12624
12628
|
try {
|
|
12625
12629
|
const res = await fetch(`${url2}/api/health`);
|
|
12626
12630
|
if (res.ok) return true;
|
|
@@ -12662,11 +12666,14 @@ async function startServiceMode(openBrowser) {
|
|
|
12662
12666
|
v2.info("Check logs with: truecourse service logs");
|
|
12663
12667
|
}
|
|
12664
12668
|
}
|
|
12669
|
+
function getServerProcess() {
|
|
12670
|
+
return _serverProcess;
|
|
12671
|
+
}
|
|
12665
12672
|
function startConsoleMode(openBrowser) {
|
|
12666
12673
|
const serverPath = getServerPath();
|
|
12667
12674
|
const url2 = getServerUrl();
|
|
12668
12675
|
v2.step("Starting server (embedded PostgreSQL starts automatically)...");
|
|
12669
|
-
const serverProcess = spawn2(
|
|
12676
|
+
const serverProcess = _serverProcess = spawn2(
|
|
12670
12677
|
process.execPath,
|
|
12671
12678
|
[serverPath],
|
|
12672
12679
|
{
|
|
@@ -12709,7 +12716,7 @@ async function runStart({ openBrowser = true } = {}) {
|
|
|
12709
12716
|
startConsoleMode(openBrowser);
|
|
12710
12717
|
}
|
|
12711
12718
|
}
|
|
12712
|
-
var __dirname;
|
|
12719
|
+
var __dirname, _serverProcess;
|
|
12713
12720
|
var init_start = __esm({
|
|
12714
12721
|
"tools/cli/src/commands/start.ts"() {
|
|
12715
12722
|
"use strict";
|
|
@@ -12718,6 +12725,7 @@ var init_start = __esm({
|
|
|
12718
12725
|
init_platform();
|
|
12719
12726
|
init_logs();
|
|
12720
12727
|
__dirname = path4.dirname(fileURLToPath(import.meta.url));
|
|
12728
|
+
_serverProcess = null;
|
|
12721
12729
|
}
|
|
12722
12730
|
});
|
|
12723
12731
|
|
|
@@ -12730,6 +12738,7 @@ __export(helpers_exports, {
|
|
|
12730
12738
|
getConfigPath: () => getConfigPath,
|
|
12731
12739
|
getServerUrl: () => getServerUrl,
|
|
12732
12740
|
openInBrowser: () => openInBrowser,
|
|
12741
|
+
promptInstallSkills: () => promptInstallSkills,
|
|
12733
12742
|
readConfig: () => readConfig,
|
|
12734
12743
|
renderDiffResults: () => renderDiffResults,
|
|
12735
12744
|
renderDiffResultsSummary: () => renderDiffResultsSummary,
|
|
@@ -12740,8 +12749,11 @@ __export(helpers_exports, {
|
|
|
12740
12749
|
writeConfig: () => writeConfig
|
|
12741
12750
|
});
|
|
12742
12751
|
import { exec } from "node:child_process";
|
|
12752
|
+
import { cpSync, existsSync } from "node:fs";
|
|
12743
12753
|
import fs5 from "node:fs";
|
|
12744
12754
|
import path5 from "node:path";
|
|
12755
|
+
import { dirname, resolve } from "node:path";
|
|
12756
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
12745
12757
|
import os4 from "node:os";
|
|
12746
12758
|
function getConfigPath() {
|
|
12747
12759
|
return path5.join(os4.homedir(), ".truecourse", "config.json");
|
|
@@ -12775,16 +12787,28 @@ async function ensureServer() {
|
|
|
12775
12787
|
if (!res.ok) throw new Error(`Server returned ${res.status}`);
|
|
12776
12788
|
return false;
|
|
12777
12789
|
} catch {
|
|
12778
|
-
const
|
|
12790
|
+
const envPath = path5.join(os4.homedir(), ".truecourse", ".env");
|
|
12791
|
+
if (!fs5.existsSync(envPath)) {
|
|
12792
|
+
const { runSetup: runSetup2 } = await Promise.resolve().then(() => (init_setup(), setup_exports));
|
|
12793
|
+
await runSetup2();
|
|
12794
|
+
}
|
|
12795
|
+
const { runStart: runStart2, getServerProcess: getServerProcess2 } = await Promise.resolve().then(() => (init_start(), start_exports));
|
|
12779
12796
|
await runStart2({ openBrowser: false });
|
|
12780
|
-
|
|
12781
|
-
const
|
|
12782
|
-
if (!
|
|
12783
|
-
}
|
|
12784
|
-
|
|
12785
|
-
|
|
12797
|
+
const killServer = () => {
|
|
12798
|
+
const proc = getServerProcess2();
|
|
12799
|
+
if (proc && !proc.killed) proc.kill("SIGTERM");
|
|
12800
|
+
};
|
|
12801
|
+
process.on("exit", killServer);
|
|
12802
|
+
for (let i = 0; i < 120; i++) {
|
|
12803
|
+
try {
|
|
12804
|
+
const res = await fetch(`${url2}/api/health`);
|
|
12805
|
+
if (res.ok) return true;
|
|
12806
|
+
} catch {
|
|
12807
|
+
}
|
|
12808
|
+
await new Promise((r2) => setTimeout(r2, 500));
|
|
12786
12809
|
}
|
|
12787
|
-
|
|
12810
|
+
v2.error("Server failed to start. Check logs with: truecourse service logs");
|
|
12811
|
+
process.exit(1);
|
|
12788
12812
|
}
|
|
12789
12813
|
}
|
|
12790
12814
|
async function ensureRepo() {
|
|
@@ -12807,7 +12831,11 @@ async function ensureRepo() {
|
|
|
12807
12831
|
v2.error(message);
|
|
12808
12832
|
process.exit(1);
|
|
12809
12833
|
}
|
|
12810
|
-
|
|
12834
|
+
const repo = await res.json();
|
|
12835
|
+
if (res.status === 201) {
|
|
12836
|
+
await promptInstallSkills(process.cwd());
|
|
12837
|
+
}
|
|
12838
|
+
return repo;
|
|
12811
12839
|
}
|
|
12812
12840
|
function connectSocket(repoId) {
|
|
12813
12841
|
const url2 = getServerUrl();
|
|
@@ -13005,6 +13033,26 @@ function openInBrowser(url2) {
|
|
|
13005
13033
|
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
13006
13034
|
exec(`${cmd} ${url2}`);
|
|
13007
13035
|
}
|
|
13036
|
+
async function promptInstallSkills(repoPath) {
|
|
13037
|
+
const installSkills = await me({
|
|
13038
|
+
message: "Would you like to install Claude Code skills?"
|
|
13039
|
+
});
|
|
13040
|
+
if (BD(installSkills) || !installSkills) return;
|
|
13041
|
+
const __dirname3 = dirname(fileURLToPath2(import.meta.url));
|
|
13042
|
+
const srcPath = resolve(__dirname3, "..", "..", "skills", "truecourse");
|
|
13043
|
+
const distPath = resolve(__dirname3, "skills", "truecourse");
|
|
13044
|
+
const skillsSrc = existsSync(srcPath) ? srcPath : distPath;
|
|
13045
|
+
if (!existsSync(skillsSrc)) {
|
|
13046
|
+
v2.warn("Skills directory not found in package \u2014 skipping.");
|
|
13047
|
+
return;
|
|
13048
|
+
}
|
|
13049
|
+
const skillsDest = resolve(repoPath, ".claude", "skills");
|
|
13050
|
+
cpSync(skillsSrc, skillsDest, { recursive: true });
|
|
13051
|
+
v2.success("Installed Claude Code skills:");
|
|
13052
|
+
v2.message(" - truecourse-analyze (run analysis)");
|
|
13053
|
+
v2.message(" - truecourse-list (list violations)");
|
|
13054
|
+
v2.message(" - truecourse-fix (apply fixes)");
|
|
13055
|
+
}
|
|
13008
13056
|
var DEFAULT_PORT, DEFAULT_CONFIG;
|
|
13009
13057
|
var init_helpers = __esm({
|
|
13010
13058
|
"tools/cli/src/commands/helpers.ts"() {
|
|
@@ -13016,39 +13064,15 @@ var init_helpers = __esm({
|
|
|
13016
13064
|
}
|
|
13017
13065
|
});
|
|
13018
13066
|
|
|
13019
|
-
// node_modules/.pnpm/commander@12.1.0/node_modules/commander/esm.mjs
|
|
13020
|
-
var import_index = __toESM(require_commander(), 1);
|
|
13021
|
-
var {
|
|
13022
|
-
program,
|
|
13023
|
-
createCommand,
|
|
13024
|
-
createArgument,
|
|
13025
|
-
createOption,
|
|
13026
|
-
CommanderError,
|
|
13027
|
-
InvalidArgumentError,
|
|
13028
|
-
InvalidOptionArgumentError,
|
|
13029
|
-
// deprecated old name
|
|
13030
|
-
Command,
|
|
13031
|
-
Argument,
|
|
13032
|
-
Option,
|
|
13033
|
-
Help
|
|
13034
|
-
} = import_index.default;
|
|
13035
|
-
|
|
13036
|
-
// tools/cli/src/index.ts
|
|
13037
|
-
init_dist2();
|
|
13038
|
-
import fs7 from "node:fs";
|
|
13039
|
-
import path8 from "node:path";
|
|
13040
|
-
import os6 from "node:os";
|
|
13041
|
-
|
|
13042
13067
|
// tools/cli/src/commands/setup.ts
|
|
13043
|
-
|
|
13068
|
+
var setup_exports = {};
|
|
13069
|
+
__export(setup_exports, {
|
|
13070
|
+
runSetup: () => runSetup
|
|
13071
|
+
});
|
|
13044
13072
|
import { execSync as execSync4 } from "node:child_process";
|
|
13045
13073
|
import fs6 from "node:fs";
|
|
13046
13074
|
import path6 from "node:path";
|
|
13047
13075
|
import os5 from "node:os";
|
|
13048
|
-
var DEFAULT_MODELS = {
|
|
13049
|
-
anthropic: "claude-sonnet-4-20250514",
|
|
13050
|
-
openai: "gpt-5.3-codex"
|
|
13051
|
-
};
|
|
13052
13076
|
function buildEnvContents(config) {
|
|
13053
13077
|
const lines = [
|
|
13054
13078
|
"# TrueCourse Environment Configuration",
|
|
@@ -13194,8 +13218,8 @@ async function runSetup() {
|
|
|
13194
13218
|
const runMode = await de({
|
|
13195
13219
|
message: "How would you like to run TrueCourse?",
|
|
13196
13220
|
options: [
|
|
13197
|
-
{ value: "
|
|
13198
|
-
{ value: "
|
|
13221
|
+
{ value: "service", label: "Background service (Recommended)" },
|
|
13222
|
+
{ value: "console", label: "Console (keep terminal open)" }
|
|
13199
13223
|
]
|
|
13200
13224
|
});
|
|
13201
13225
|
if (BD(runMode)) {
|
|
@@ -13211,16 +13235,46 @@ async function runSetup() {
|
|
|
13211
13235
|
v2.info("Database migrations are applied on server startup.");
|
|
13212
13236
|
fe("Setup complete!");
|
|
13213
13237
|
}
|
|
13238
|
+
var DEFAULT_MODELS;
|
|
13239
|
+
var init_setup = __esm({
|
|
13240
|
+
"tools/cli/src/commands/setup.ts"() {
|
|
13241
|
+
"use strict";
|
|
13242
|
+
init_dist2();
|
|
13243
|
+
DEFAULT_MODELS = {
|
|
13244
|
+
anthropic: "claude-sonnet-4-20250514",
|
|
13245
|
+
openai: "gpt-5.3-codex"
|
|
13246
|
+
};
|
|
13247
|
+
}
|
|
13248
|
+
});
|
|
13249
|
+
|
|
13250
|
+
// node_modules/.pnpm/commander@12.1.0/node_modules/commander/esm.mjs
|
|
13251
|
+
var import_index = __toESM(require_commander(), 1);
|
|
13252
|
+
var {
|
|
13253
|
+
program,
|
|
13254
|
+
createCommand,
|
|
13255
|
+
createArgument,
|
|
13256
|
+
createOption,
|
|
13257
|
+
CommanderError,
|
|
13258
|
+
InvalidArgumentError,
|
|
13259
|
+
InvalidOptionArgumentError,
|
|
13260
|
+
// deprecated old name
|
|
13261
|
+
Command,
|
|
13262
|
+
Argument,
|
|
13263
|
+
Option,
|
|
13264
|
+
Help
|
|
13265
|
+
} = import_index.default;
|
|
13214
13266
|
|
|
13215
13267
|
// tools/cli/src/index.ts
|
|
13268
|
+
init_dist2();
|
|
13269
|
+
init_setup();
|
|
13216
13270
|
init_start();
|
|
13271
|
+
import fs7 from "node:fs";
|
|
13272
|
+
import path8 from "node:path";
|
|
13273
|
+
import os6 from "node:os";
|
|
13217
13274
|
|
|
13218
13275
|
// tools/cli/src/commands/add.ts
|
|
13219
13276
|
init_dist2();
|
|
13220
13277
|
init_helpers();
|
|
13221
|
-
import { cpSync, existsSync } from "node:fs";
|
|
13222
|
-
import { resolve, dirname } from "node:path";
|
|
13223
|
-
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
13224
13278
|
async function runAdd() {
|
|
13225
13279
|
const repoPath = process.cwd();
|
|
13226
13280
|
const serverUrl = getServerUrl();
|
|
@@ -13247,27 +13301,7 @@ async function runAdd() {
|
|
|
13247
13301
|
const repo = await res.json();
|
|
13248
13302
|
const repoUrl = `${serverUrl}/repos/${repo.id}`;
|
|
13249
13303
|
v2.success(`Repository "${repo.name}" added`);
|
|
13250
|
-
|
|
13251
|
-
message: "Would you like to install Claude Code skills?"
|
|
13252
|
-
});
|
|
13253
|
-
if (BD(installSkills)) {
|
|
13254
|
-
fe(`Open ${repoUrl}`);
|
|
13255
|
-
return;
|
|
13256
|
-
}
|
|
13257
|
-
if (installSkills) {
|
|
13258
|
-
const cliDir = dirname(fileURLToPath2(import.meta.url));
|
|
13259
|
-
const skillsSrc = resolve(cliDir, "..", "..", "skills", "truecourse");
|
|
13260
|
-
if (!existsSync(skillsSrc)) {
|
|
13261
|
-
v2.warn("Skills directory not found in package \u2014 skipping.");
|
|
13262
|
-
} else {
|
|
13263
|
-
const skillsDest = resolve(repoPath, ".claude", "skills", "truecourse");
|
|
13264
|
-
cpSync(skillsSrc, skillsDest, { recursive: true });
|
|
13265
|
-
v2.success("Installed Claude Code skills:");
|
|
13266
|
-
v2.message(" - truecourse-analyze (run analysis)");
|
|
13267
|
-
v2.message(" - truecourse-list (list violations)");
|
|
13268
|
-
v2.message(" - truecourse-fix (apply fixes)");
|
|
13269
|
-
}
|
|
13270
|
-
}
|
|
13304
|
+
await promptInstallSkills(repoPath);
|
|
13271
13305
|
fe(`Open ${repoUrl}`);
|
|
13272
13306
|
} catch (err) {
|
|
13273
13307
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -13286,15 +13320,37 @@ async function runAdd() {
|
|
|
13286
13320
|
init_dist2();
|
|
13287
13321
|
init_helpers();
|
|
13288
13322
|
var TIMEOUT_MS = 15 * 60 * 1e3;
|
|
13289
|
-
async function runAnalyze() {
|
|
13323
|
+
async function runAnalyze({ noAutostart = false } = {}) {
|
|
13290
13324
|
we("Analyzing repository");
|
|
13291
|
-
|
|
13325
|
+
if (noAutostart) {
|
|
13326
|
+
const url2 = getServerUrl();
|
|
13327
|
+
try {
|
|
13328
|
+
const res = await fetch(`${url2}/api/health`);
|
|
13329
|
+
if (!res.ok) throw new Error();
|
|
13330
|
+
} catch {
|
|
13331
|
+
v2.error("TrueCourse server is not running. Start it with: npx truecourse start");
|
|
13332
|
+
process.exit(1);
|
|
13333
|
+
}
|
|
13334
|
+
}
|
|
13335
|
+
const firstRun = noAutostart ? false : await ensureServer();
|
|
13292
13336
|
const repo = await ensureRepo();
|
|
13293
13337
|
v2.step(`Repository: ${repo.name}`);
|
|
13294
13338
|
const serverUrl = getServerUrl();
|
|
13295
13339
|
const socket = connectSocket(repo.id);
|
|
13296
13340
|
const spinner = L2();
|
|
13297
13341
|
spinner.start("Starting analysis...");
|
|
13342
|
+
let canceled = false;
|
|
13343
|
+
const onSigint = () => {
|
|
13344
|
+
if (canceled) return;
|
|
13345
|
+
canceled = true;
|
|
13346
|
+
spinner.stop("Cancelling analysis...");
|
|
13347
|
+
fetch(`${serverUrl}/api/repos/${repo.id}/analyze/cancel`, { method: "POST" }).catch(() => {
|
|
13348
|
+
}).finally(() => {
|
|
13349
|
+
socket.disconnect();
|
|
13350
|
+
process.exit(130);
|
|
13351
|
+
});
|
|
13352
|
+
};
|
|
13353
|
+
process.on("SIGINT", onSigint);
|
|
13298
13354
|
try {
|
|
13299
13355
|
await new Promise((resolve2, reject) => {
|
|
13300
13356
|
const timeout = setTimeout(() => {
|
|
@@ -13321,6 +13377,10 @@ async function runAnalyze() {
|
|
|
13321
13377
|
violationsReady = true;
|
|
13322
13378
|
checkDone();
|
|
13323
13379
|
});
|
|
13380
|
+
socket.on("analysis:canceled", () => {
|
|
13381
|
+
clearTimeout(timeout);
|
|
13382
|
+
reject(new Error("CANCELED"));
|
|
13383
|
+
});
|
|
13324
13384
|
fetch(`${serverUrl}/api/repos/${repo.id}/analyze`, {
|
|
13325
13385
|
method: "POST",
|
|
13326
13386
|
headers: { "Content-Type": "application/json" },
|
|
@@ -13360,17 +13420,34 @@ async function runAnalyze() {
|
|
|
13360
13420
|
fe(`Analysis complete \u2014 open ${repoUrl}`);
|
|
13361
13421
|
}
|
|
13362
13422
|
} catch (err) {
|
|
13363
|
-
spinner.stop("Analysis failed");
|
|
13364
13423
|
const message = err instanceof Error ? err.message : String(err);
|
|
13365
|
-
|
|
13366
|
-
|
|
13424
|
+
if (message === "CANCELED") {
|
|
13425
|
+
spinner.stop("Analysis cancelled");
|
|
13426
|
+
fe("Analysis cancelled");
|
|
13427
|
+
} else {
|
|
13428
|
+
spinner.stop("Analysis failed");
|
|
13429
|
+
v2.error(message);
|
|
13430
|
+
process.exit(1);
|
|
13431
|
+
}
|
|
13367
13432
|
} finally {
|
|
13433
|
+
process.removeListener("SIGINT", onSigint);
|
|
13368
13434
|
socket.disconnect();
|
|
13369
13435
|
}
|
|
13370
13436
|
}
|
|
13371
|
-
async function runAnalyzeDiff() {
|
|
13437
|
+
async function runAnalyzeDiff({ noAutostart = false } = {}) {
|
|
13372
13438
|
we("Running diff check");
|
|
13373
|
-
|
|
13439
|
+
if (noAutostart) {
|
|
13440
|
+
const url2 = getServerUrl();
|
|
13441
|
+
try {
|
|
13442
|
+
const res = await fetch(`${url2}/api/health`);
|
|
13443
|
+
if (!res.ok) throw new Error();
|
|
13444
|
+
} catch {
|
|
13445
|
+
v2.error("TrueCourse server is not running. Start it with: npx truecourse start");
|
|
13446
|
+
process.exit(1);
|
|
13447
|
+
}
|
|
13448
|
+
} else {
|
|
13449
|
+
await ensureServer();
|
|
13450
|
+
}
|
|
13374
13451
|
const repo = await ensureRepo();
|
|
13375
13452
|
v2.step(`Repository: ${repo.name}`);
|
|
13376
13453
|
const serverUrl = getServerUrl();
|
|
@@ -13622,11 +13699,11 @@ program2.command("start").description("Start TrueCourse services").action(async
|
|
|
13622
13699
|
program2.command("add").description("Add the current directory as a repository").action(async () => {
|
|
13623
13700
|
await runAdd();
|
|
13624
13701
|
});
|
|
13625
|
-
program2.command("analyze").description("Analyze the current repository").option("--diff", "Run diff check against latest analysis").action(async (options) => {
|
|
13702
|
+
program2.command("analyze").description("Analyze the current repository").option("--diff", "Run diff check against latest analysis").option("--no-autostart", "Don't auto-start the server (for use from Claude Code skills)").action(async (options) => {
|
|
13626
13703
|
if (options.diff) {
|
|
13627
|
-
await runAnalyzeDiff();
|
|
13704
|
+
await runAnalyzeDiff({ noAutostart: !options.autostart });
|
|
13628
13705
|
} else {
|
|
13629
|
-
await runAnalyze();
|
|
13706
|
+
await runAnalyze({ noAutostart: !options.autostart });
|
|
13630
13707
|
}
|
|
13631
13708
|
});
|
|
13632
13709
|
program2.command("list").description("List violations from the latest analysis").option("--diff", "Show diff check results (new and resolved)").action(async (options) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "truecourse",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"description": "Visualize your codebase architecture as an interactive graph",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
"dotenv": "^16.4.0",
|
|
16
16
|
"embedded-postgres": "18.3.0-beta.16",
|
|
17
17
|
"postgres": "^3.4.0",
|
|
18
|
-
"tree-sitter": "^0.
|
|
19
|
-
"tree-sitter-javascript": "^0.
|
|
20
|
-
"tree-sitter-typescript": "^0.
|
|
18
|
+
"tree-sitter": "^0.25.0",
|
|
19
|
+
"tree-sitter-javascript": "^0.25.0",
|
|
20
|
+
"tree-sitter-typescript": "^0.23.2"
|
|
21
21
|
},
|
|
22
22
|
"optionalDependencies": {
|
|
23
23
|
"node-windows": "^1.0.0-beta.8"
|