postgresai 0.15.0-dev.7 → 0.15.0-dev.9
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 +3 -1
- package/bin/postgres-ai.ts +93 -57
- package/bun.lock +4 -4
- package/dist/bin/postgres-ai.js +855 -222
- package/instances.demo.yml +14 -0
- package/lib/checkup-api.ts +25 -6
- package/lib/checkup.ts +225 -0
- package/lib/init.ts +195 -3
- package/lib/metrics-loader.ts +3 -1
- package/lib/supabase.ts +8 -1
- package/package.json +4 -4
- package/scripts/embed-checkup-dictionary.ts +9 -0
- package/scripts/embed-metrics.ts +2 -0
- package/test/PERMISSION_CHECK_TEST_SUMMARY.md +139 -0
- package/test/checkup.test.ts +1288 -2
- package/test/config-consistency.test.ts +321 -5
- package/test/init.integration.test.ts +27 -28
- package/test/init.test.ts +469 -4
- package/test/permission-check-sql.test.ts +116 -0
- package/test/schema-validation.test.ts +81 -0
- package/test/test-utils.ts +51 -2
- package/test/upgrade.test.ts +422 -0
package/README.md
CHANGED
|
@@ -173,7 +173,7 @@ postgresai mon local-install --api-key your_key --db-url postgresql://user:pass@
|
|
|
173
173
|
This will:
|
|
174
174
|
- Configure API key for automated report uploads (if provided)
|
|
175
175
|
- Add PostgreSQL instance to monitor (if provided)
|
|
176
|
-
- Generate secure Grafana
|
|
176
|
+
- Generate secure Grafana and replication passwords
|
|
177
177
|
- Start all monitoring services
|
|
178
178
|
- Open Grafana at http://localhost:3000
|
|
179
179
|
|
|
@@ -205,6 +205,8 @@ postgresai mon health [--wait <sec>] # Check monitoring services health
|
|
|
205
205
|
- `--db-url <url>` - PostgreSQL connection URL to monitor (format: `postgresql://user:pass@host:port/db`)
|
|
206
206
|
- `-y, --yes` - Accept all defaults and skip interactive prompts
|
|
207
207
|
|
|
208
|
+
`local-install` writes `.env` in the monitoring directory. It preserves existing `REPLICATOR_PASSWORD` and `VM_AUTH_*` values or generates new random ones when missing; `VM_AUTH_USERNAME` defaults to `vmauth` when absent. The replication password is used by the demo PostgreSQL standby replication user, and the VM auth credentials are required before Docker Compose can provision Grafana datasources. If you run `docker compose` directly or maintain `.env` yourself, set both VM auth values before upgrading. For rotation, run `VM_AUTH_PASSWORD="$(openssl rand -base64 18)" ./scripts/rotate-vm-auth.sh` from the monitoring directory so `.env`, `sink-prometheus`, and `grafana` update together.
|
|
209
|
+
|
|
208
210
|
#### Monitoring target databases (`mon targets` subgroup)
|
|
209
211
|
```bash
|
|
210
212
|
postgresai mon targets list # List databases to monitor
|
package/bin/postgres-ai.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { fetchIssues, fetchIssueComments, createIssueComment, fetchIssue, create
|
|
|
15
15
|
import { fetchReports, fetchAllReports, fetchReportFiles, fetchReportFileData, renderMarkdownForTerminal, parseFlexibleDate } from "../lib/reports";
|
|
16
16
|
import { resolveBaseUrls } from "../lib/util";
|
|
17
17
|
import { uploadFile, downloadFile, buildMarkdownLink } from "../lib/storage";
|
|
18
|
-
import { applyInitPlan, applyUninitPlan, buildInitPlan, buildUninitPlan, connectWithSslFallback, DEFAULT_MONITORING_USER, KNOWN_PROVIDERS, redactPasswordsInSql, resolveAdminConnection, resolveMonitoringPassword, validateProvider, verifyInitSetup } from "../lib/init";
|
|
18
|
+
import { applyInitPlan, applyUninitPlan, buildInitPlan, buildUninitPlan, checkCurrentUserPermissions, connectWithSslFallback, DEFAULT_MONITORING_USER, formatPermissionCheckMessages, KNOWN_PROVIDERS, redactPasswordsInSql, resolveAdminConnection, resolveMonitoringPassword, validateProvider, verifyInitSetup } from "../lib/init";
|
|
19
19
|
import { SupabaseClient, resolveSupabaseConfig, extractProjectRefFromUrl, applyInitPlanViaSupabase, verifyInitSetupViaSupabase, fetchPoolerDatabaseUrl, type PgCompatibleError } from "../lib/supabase";
|
|
20
20
|
import * as pkce from "../lib/pkce";
|
|
21
21
|
import * as authServer from "../lib/auth-server";
|
|
@@ -54,21 +54,16 @@ function closeReadline() {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
reject(err);
|
|
65
|
-
} else {
|
|
66
|
-
resolve({ stdout, stderr });
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
});
|
|
57
|
+
function stripMatchingQuotes(value: string): string {
|
|
58
|
+
const trimmed = value.trim();
|
|
59
|
+
const quote = trimmed[0];
|
|
60
|
+
if (trimmed.length >= 2 && (quote === '"' || quote === "'") && trimmed.endsWith(quote)) {
|
|
61
|
+
return trimmed.slice(1, -1);
|
|
62
|
+
}
|
|
63
|
+
return trimmed;
|
|
70
64
|
}
|
|
71
65
|
|
|
66
|
+
// Helper functions for spawning processes - use Node.js child_process for compatibility
|
|
72
67
|
async function execFilePromise(file: string, args: string[]): Promise<{ stdout: string; stderr: string }> {
|
|
73
68
|
return new Promise((resolve, reject) => {
|
|
74
69
|
childProcess.execFile(file, args, (error, stdout, stderr) => {
|
|
@@ -1831,6 +1826,24 @@ program
|
|
|
1831
1826
|
const connResult = await connectWithSslFallback(Client, adminConn);
|
|
1832
1827
|
client = connResult.client as Client;
|
|
1833
1828
|
|
|
1829
|
+
// Preflight: verify the connected user has sufficient permissions
|
|
1830
|
+
spinner.update("Checking database permissions");
|
|
1831
|
+
const permCheck = await checkCurrentUserPermissions(client);
|
|
1832
|
+
const permMessages = formatPermissionCheckMessages(permCheck);
|
|
1833
|
+
|
|
1834
|
+
for (const w of permMessages.warnings) {
|
|
1835
|
+
console.error(w);
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
if (permMessages.failed) {
|
|
1839
|
+
spinner.stop();
|
|
1840
|
+
for (const e of permMessages.errors) {
|
|
1841
|
+
console.error(e);
|
|
1842
|
+
}
|
|
1843
|
+
process.exitCode = 1;
|
|
1844
|
+
return;
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1834
1847
|
// Generate reports
|
|
1835
1848
|
let reports: Record<string, any>;
|
|
1836
1849
|
if (checkId === "ALL") {
|
|
@@ -2250,11 +2263,11 @@ async function runCompose(args: string[], grafanaPassword?: string): Promise<num
|
|
|
2250
2263
|
const envContent = fs.readFileSync(envFilePath, "utf8");
|
|
2251
2264
|
if (!env.VM_AUTH_USERNAME) {
|
|
2252
2265
|
const m = envContent.match(/^VM_AUTH_USERNAME=([^\r\n]+)/m);
|
|
2253
|
-
if (m) env.VM_AUTH_USERNAME = m[1]
|
|
2266
|
+
if (m) env.VM_AUTH_USERNAME = stripMatchingQuotes(m[1]);
|
|
2254
2267
|
}
|
|
2255
2268
|
if (!env.VM_AUTH_PASSWORD) {
|
|
2256
2269
|
const m = envContent.match(/^VM_AUTH_PASSWORD=([^\r\n]+)/m);
|
|
2257
|
-
if (m) env.VM_AUTH_PASSWORD = m[1]
|
|
2270
|
+
if (m) env.VM_AUTH_PASSWORD = stripMatchingQuotes(m[1]);
|
|
2258
2271
|
}
|
|
2259
2272
|
} catch (err) {
|
|
2260
2273
|
if (process.env.DEBUG) {
|
|
@@ -2320,10 +2333,13 @@ mon
|
|
|
2320
2333
|
// Update .env with custom tag if provided
|
|
2321
2334
|
const envFile = path.resolve(projectDir, ".env");
|
|
2322
2335
|
|
|
2323
|
-
// Build .env content, preserving important existing values
|
|
2324
|
-
// Note: PGAI_TAG is intentionally NOT preserved - the CLI version should always match Docker images
|
|
2336
|
+
// Build .env content, preserving important existing values.
|
|
2337
|
+
// Note: PGAI_TAG is intentionally NOT preserved - the CLI version should always match Docker images.
|
|
2325
2338
|
let existingRegistry: string | null = null;
|
|
2326
2339
|
let existingPassword: string | null = null;
|
|
2340
|
+
let existingReplicatorPassword: string | null = null;
|
|
2341
|
+
let existingVmAuthUsername: string | null = null;
|
|
2342
|
+
let existingVmAuthPassword: string | null = null;
|
|
2327
2343
|
|
|
2328
2344
|
if (fs.existsSync(envFile)) {
|
|
2329
2345
|
const existingEnv = fs.readFileSync(envFile, "utf8");
|
|
@@ -2332,6 +2348,12 @@ mon
|
|
|
2332
2348
|
if (registryMatch) existingRegistry = registryMatch[1].trim();
|
|
2333
2349
|
const pwdMatch = existingEnv.match(/^GF_SECURITY_ADMIN_PASSWORD=(.+)$/m);
|
|
2334
2350
|
if (pwdMatch) existingPassword = pwdMatch[1].trim();
|
|
2351
|
+
const replicatorPwdMatch = existingEnv.match(/^REPLICATOR_PASSWORD=(.+)$/m);
|
|
2352
|
+
if (replicatorPwdMatch) existingReplicatorPassword = replicatorPwdMatch[1].trim();
|
|
2353
|
+
const vmAuthUserMatch = existingEnv.match(/^VM_AUTH_USERNAME=(.+)$/m);
|
|
2354
|
+
if (vmAuthUserMatch) existingVmAuthUsername = stripMatchingQuotes(vmAuthUserMatch[1]);
|
|
2355
|
+
const vmAuthPasswordMatch = existingEnv.match(/^VM_AUTH_PASSWORD=(.+)$/m);
|
|
2356
|
+
if (vmAuthPasswordMatch) existingVmAuthPassword = stripMatchingQuotes(vmAuthPasswordMatch[1]);
|
|
2335
2357
|
}
|
|
2336
2358
|
|
|
2337
2359
|
// Priority: CLI --tag flag > package version
|
|
@@ -2347,6 +2369,11 @@ mon
|
|
|
2347
2369
|
if (existingPassword) {
|
|
2348
2370
|
envLines.push(`GF_SECURITY_ADMIN_PASSWORD=${existingPassword}`);
|
|
2349
2371
|
}
|
|
2372
|
+
envLines.push(
|
|
2373
|
+
`REPLICATOR_PASSWORD=${existingReplicatorPassword || crypto.randomBytes(32).toString("hex")}`,
|
|
2374
|
+
);
|
|
2375
|
+
envLines.push(`VM_AUTH_USERNAME=${existingVmAuthUsername || "vmauth"}`);
|
|
2376
|
+
envLines.push(`VM_AUTH_PASSWORD=${existingVmAuthPassword || crypto.randomBytes(18).toString("base64")}`);
|
|
2350
2377
|
fs.writeFileSync(envFile, envLines.join("\n") + "\n", { encoding: "utf8", mode: 0o600 });
|
|
2351
2378
|
|
|
2352
2379
|
if (opts.tag) {
|
|
@@ -2466,16 +2493,20 @@ mon
|
|
|
2466
2493
|
|
|
2467
2494
|
// Test connection
|
|
2468
2495
|
console.log("Testing connection to the added instance...");
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2496
|
+
{
|
|
2497
|
+
let testClient: InstanceType<typeof Client> | null = null;
|
|
2498
|
+
try {
|
|
2499
|
+
testClient = new Client({ connectionString: connStr, connectionTimeoutMillis: 10000 });
|
|
2500
|
+
await testClient.connect();
|
|
2501
|
+
const result = await testClient.query("select version();");
|
|
2502
|
+
console.log("✓ Connection successful");
|
|
2503
|
+
console.log(`${result.rows[0].version}\n`);
|
|
2504
|
+
} catch (error) {
|
|
2505
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2506
|
+
console.error(`✗ Connection failed: ${message}\n`);
|
|
2507
|
+
} finally {
|
|
2508
|
+
if (testClient) await testClient.end();
|
|
2509
|
+
}
|
|
2479
2510
|
}
|
|
2480
2511
|
} else if (opts.yes) {
|
|
2481
2512
|
// Auto-yes mode without database URL - skip database setup
|
|
@@ -2510,16 +2541,20 @@ mon
|
|
|
2510
2541
|
|
|
2511
2542
|
// Test connection
|
|
2512
2543
|
console.log("Testing connection to the added instance...");
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2544
|
+
{
|
|
2545
|
+
let testClient: InstanceType<typeof Client> | null = null;
|
|
2546
|
+
try {
|
|
2547
|
+
testClient = new Client({ connectionString: connStr, connectionTimeoutMillis: 10000 });
|
|
2548
|
+
await testClient.connect();
|
|
2549
|
+
const result = await testClient.query("select version();");
|
|
2550
|
+
console.log("✓ Connection successful");
|
|
2551
|
+
console.log(`${result.rows[0].version}\n`);
|
|
2552
|
+
} catch (error) {
|
|
2553
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2554
|
+
console.error(`✗ Connection failed: ${message}\n`);
|
|
2555
|
+
} finally {
|
|
2556
|
+
if (testClient) await testClient.end();
|
|
2557
|
+
}
|
|
2523
2558
|
}
|
|
2524
2559
|
}
|
|
2525
2560
|
} else {
|
|
@@ -2594,8 +2629,8 @@ mon
|
|
|
2594
2629
|
|
|
2595
2630
|
if (!grafanaPassword) {
|
|
2596
2631
|
console.log("Generating secure Grafana password...");
|
|
2597
|
-
const { stdout: password } = await
|
|
2598
|
-
grafanaPassword = password.trim();
|
|
2632
|
+
const { stdout: password } = await execFilePromise("openssl", ["rand", "-base64", "12"]);
|
|
2633
|
+
grafanaPassword = password.trim().replace(/\n/g, "");
|
|
2599
2634
|
|
|
2600
2635
|
let configContent = "";
|
|
2601
2636
|
if (fs.existsSync(cfgPath)) {
|
|
@@ -2626,16 +2661,16 @@ mon
|
|
|
2626
2661
|
const envContent = fs.readFileSync(envFile, "utf8");
|
|
2627
2662
|
const userMatch = envContent.match(/^VM_AUTH_USERNAME=([^\r\n]+)/m);
|
|
2628
2663
|
const passMatch = envContent.match(/^VM_AUTH_PASSWORD=([^\r\n]+)/m);
|
|
2629
|
-
if (userMatch) vmAuthUsername = userMatch[1]
|
|
2630
|
-
if (passMatch) vmAuthPassword = passMatch[1]
|
|
2664
|
+
if (userMatch) vmAuthUsername = stripMatchingQuotes(userMatch[1]);
|
|
2665
|
+
if (passMatch) vmAuthPassword = stripMatchingQuotes(passMatch[1]);
|
|
2631
2666
|
}
|
|
2632
2667
|
|
|
2633
2668
|
if (!vmAuthUsername || !vmAuthPassword) {
|
|
2634
2669
|
console.log("Generating VictoriaMetrics auth credentials...");
|
|
2635
2670
|
vmAuthUsername = vmAuthUsername || "vmauth";
|
|
2636
2671
|
if (!vmAuthPassword) {
|
|
2637
|
-
const { stdout: vmPass } = await
|
|
2638
|
-
vmAuthPassword = vmPass.trim();
|
|
2672
|
+
const { stdout: vmPass } = await execFilePromise("openssl", ["rand", "-base64", "12"]);
|
|
2673
|
+
vmAuthPassword = vmPass.trim().replace(/\n/g, "");
|
|
2639
2674
|
}
|
|
2640
2675
|
|
|
2641
2676
|
// Update .env file with VM auth credentials
|
|
@@ -2947,16 +2982,16 @@ mon
|
|
|
2947
2982
|
|
|
2948
2983
|
// Fetch latest changes
|
|
2949
2984
|
console.log("Fetching latest changes...");
|
|
2950
|
-
await
|
|
2985
|
+
await execFilePromise("git", ["fetch", "origin"]);
|
|
2951
2986
|
|
|
2952
2987
|
// Check current branch
|
|
2953
|
-
const { stdout: branch } = await
|
|
2988
|
+
const { stdout: branch } = await execFilePromise("git", ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
2954
2989
|
const currentBranch = branch.trim();
|
|
2955
2990
|
console.log(`Current branch: ${currentBranch}`);
|
|
2956
2991
|
|
|
2957
2992
|
// Pull latest changes
|
|
2958
2993
|
console.log("Pulling latest changes...");
|
|
2959
|
-
const { stdout: pullOut } = await
|
|
2994
|
+
const { stdout: pullOut } = await execFilePromise("git", ["pull", "origin", currentBranch]);
|
|
2960
2995
|
console.log(pullOut);
|
|
2961
2996
|
|
|
2962
2997
|
// Update Docker images
|
|
@@ -3214,7 +3249,8 @@ targets
|
|
|
3214
3249
|
// If YAML parsing fails, fall back to simple check
|
|
3215
3250
|
const isFile = fs.existsSync(file) && !fs.lstatSync(file).isDirectory();
|
|
3216
3251
|
const content = isFile ? fs.readFileSync(file, "utf8") : "";
|
|
3217
|
-
|
|
3252
|
+
const escapedName = instanceName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3253
|
+
if (new RegExp(`^- name: ${escapedName}$`, "m").test(content)) {
|
|
3218
3254
|
console.error(`Monitoring target '${instanceName}' already exists`);
|
|
3219
3255
|
process.exitCode = 1;
|
|
3220
3256
|
return;
|
|
@@ -3305,7 +3341,7 @@ targets
|
|
|
3305
3341
|
console.log(`Testing connection to monitoring target '${name}'...`);
|
|
3306
3342
|
|
|
3307
3343
|
// Use native pg client instead of requiring psql to be installed
|
|
3308
|
-
const client = new Client({ connectionString: instance.conn_str });
|
|
3344
|
+
const client = new Client({ connectionString: instance.conn_str, connectionTimeoutMillis: 10000 });
|
|
3309
3345
|
|
|
3310
3346
|
try {
|
|
3311
3347
|
await client.connect();
|
|
@@ -3658,10 +3694,10 @@ mon
|
|
|
3658
3694
|
|
|
3659
3695
|
try {
|
|
3660
3696
|
// Generate secure password using openssl
|
|
3661
|
-
const { stdout: password } = await
|
|
3662
|
-
"openssl rand -base64 12
|
|
3697
|
+
const { stdout: password } = await execFilePromise(
|
|
3698
|
+
"openssl", ["rand", "-base64", "12"]
|
|
3663
3699
|
);
|
|
3664
|
-
const newPassword = password.trim();
|
|
3700
|
+
const newPassword = password.trim().replace(/\n/g, "");
|
|
3665
3701
|
|
|
3666
3702
|
if (!newPassword) {
|
|
3667
3703
|
console.error("Failed to generate password");
|
|
@@ -3748,8 +3784,8 @@ mon
|
|
|
3748
3784
|
const vmPass = envContent.match(/^VM_AUTH_PASSWORD=([^\r\n]+)/m);
|
|
3749
3785
|
if (vmUser && vmPass) {
|
|
3750
3786
|
console.log("\nVictoriaMetrics credentials:");
|
|
3751
|
-
console.log(` Username: ${vmUser[1]
|
|
3752
|
-
console.log(` Password: ${vmPass[1]
|
|
3787
|
+
console.log(` Username: ${stripMatchingQuotes(vmUser[1])}`);
|
|
3788
|
+
console.log(` Password: ${stripMatchingQuotes(vmPass[1])}`);
|
|
3753
3789
|
}
|
|
3754
3790
|
}
|
|
3755
3791
|
console.log("");
|
|
@@ -4712,7 +4748,7 @@ mcp
|
|
|
4712
4748
|
// Get the path to the current pgai executable
|
|
4713
4749
|
let pgaiPath: string;
|
|
4714
4750
|
try {
|
|
4715
|
-
const execPath = await
|
|
4751
|
+
const execPath = await execFilePromise("which", ["pgai"]);
|
|
4716
4752
|
pgaiPath = execPath.stdout.trim();
|
|
4717
4753
|
} catch {
|
|
4718
4754
|
// Fallback to just "pgai" if which fails
|
|
@@ -4724,8 +4760,8 @@ mcp
|
|
|
4724
4760
|
console.log("Installing PostgresAI MCP server for Claude Code...");
|
|
4725
4761
|
|
|
4726
4762
|
try {
|
|
4727
|
-
const { stdout, stderr } = await
|
|
4728
|
-
|
|
4763
|
+
const { stdout, stderr } = await execFilePromise(
|
|
4764
|
+
"claude", ["mcp", "add", "-s", "user", "postgresai", pgaiPath, "mcp", "start"]
|
|
4729
4765
|
);
|
|
4730
4766
|
|
|
4731
4767
|
if (stdout) console.log(stdout);
|
package/bun.lock
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"name": "postgresai",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"@modelcontextprotocol/sdk": "^1.20.2",
|
|
9
|
-
"commander": "^
|
|
9
|
+
"commander": "^14.0.3",
|
|
10
10
|
"js-yaml": "^4.1.0",
|
|
11
11
|
"pg": "^8.16.3",
|
|
12
12
|
},
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"@types/pg": "^8.15.6",
|
|
17
17
|
"ajv": "^8.17.1",
|
|
18
18
|
"ajv-formats": "^3.0.1",
|
|
19
|
-
"typescript": "^
|
|
19
|
+
"typescript": "^6.0.2",
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
22
|
},
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
|
|
52
52
|
"call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
|
|
53
53
|
|
|
54
|
-
"commander": ["commander@
|
|
54
|
+
"commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="],
|
|
55
55
|
|
|
56
56
|
"content-disposition": ["content-disposition@1.0.0", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg=="],
|
|
57
57
|
|
|
@@ -233,7 +233,7 @@
|
|
|
233
233
|
|
|
234
234
|
"type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="],
|
|
235
235
|
|
|
236
|
-
"typescript": ["typescript@
|
|
236
|
+
"typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="],
|
|
237
237
|
|
|
238
238
|
"undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
|
|
239
239
|
|