@open-audio-stack/core 0.1.17 → 0.1.18
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/build/classes/Base.js +3 -0
- package/build/classes/ManagerLocal.js +12 -12
- package/build/classes/Package.js +2 -2
- package/build/helpers/admin.js +2 -1
- package/build/helpers/api.js +4 -3
- package/build/helpers/file.js +25 -24
- package/build/helpers/package.d.ts +0 -2
- package/build/helpers/packageLocal.js +3 -3
- package/build/helpers/utils.d.ts +3 -0
- package/build/helpers/utils.js +11 -0
- package/build/types/PluginType.d.ts +0 -1
- package/build/types/PluginType.js +0 -6
- package/package.json +4 -4
package/build/classes/Base.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
+
import { logEnable, logDisable } from '../helpers/utils.js';
|
|
2
3
|
export class Base {
|
|
3
4
|
debug = false;
|
|
4
5
|
log(...args) {
|
|
@@ -6,9 +7,11 @@ export class Base {
|
|
|
6
7
|
console.log(...args);
|
|
7
8
|
}
|
|
8
9
|
logEnable() {
|
|
10
|
+
logEnable();
|
|
9
11
|
return (this.debug = true);
|
|
10
12
|
}
|
|
11
13
|
logDisable() {
|
|
14
|
+
logDisable();
|
|
12
15
|
return (this.debug = false);
|
|
13
16
|
}
|
|
14
17
|
logErrors(errors) {
|
|
@@ -154,11 +154,11 @@ export class ManagerLocal extends Manager {
|
|
|
154
154
|
// Get package information from registry.
|
|
155
155
|
const pkg = this.getPackage(slug);
|
|
156
156
|
if (!pkg)
|
|
157
|
-
return
|
|
157
|
+
return this.log(`Package ${slug} not found in registry`);
|
|
158
158
|
const versionNum = version || pkg.latestVersion();
|
|
159
159
|
const pkgVersion = pkg?.getVersion(versionNum);
|
|
160
160
|
if (!pkgVersion)
|
|
161
|
-
return
|
|
161
|
+
return this.log(`Package ${slug} version ${versionNum} not found in registry`);
|
|
162
162
|
if (pkgVersion.installed)
|
|
163
163
|
return pkgVersion;
|
|
164
164
|
// Elevate permissions if not running as admin.
|
|
@@ -184,7 +184,7 @@ export class ManagerLocal extends Manager {
|
|
|
184
184
|
// Filter for compatible files and download.
|
|
185
185
|
const files = packageCompatibleFiles(pkgVersion, [getArchitecture()], [getSystem()], excludedFormats);
|
|
186
186
|
if (!files.length)
|
|
187
|
-
return
|
|
187
|
+
return this.log(`Error: No compatible files found for ${slug}`);
|
|
188
188
|
for (const key in files) {
|
|
189
189
|
// Download file to temporary directory if not already downloaded.
|
|
190
190
|
const file = files[key];
|
|
@@ -196,7 +196,7 @@ export class ManagerLocal extends Manager {
|
|
|
196
196
|
// Check file hash matches expected hash.
|
|
197
197
|
const hash = await fileHash(filePath);
|
|
198
198
|
if (hash !== file.sha256)
|
|
199
|
-
return
|
|
199
|
+
return this.log(`Error: ${filePath} hash mismatch`);
|
|
200
200
|
// If installer, run the installer headless (without the user interface).
|
|
201
201
|
if (file.type === FileType.Installer) {
|
|
202
202
|
if (isTests())
|
|
@@ -231,15 +231,15 @@ export class ManagerLocal extends Manager {
|
|
|
231
231
|
await manager.sync();
|
|
232
232
|
const pkg = manager.getPackage(slug);
|
|
233
233
|
if (!pkg)
|
|
234
|
-
return
|
|
234
|
+
return this.log(`Package ${slug} not found in registry`);
|
|
235
235
|
const versionNum = version || pkg.latestVersion();
|
|
236
236
|
const pkgVersion = pkg?.getVersion(versionNum);
|
|
237
237
|
if (!pkgVersion)
|
|
238
|
-
return
|
|
238
|
+
return this.log(`Package ${slug} version ${versionNum} not found in registry`);
|
|
239
239
|
// Get local package file.
|
|
240
240
|
const pkgFile = packageLoadFile(filePath);
|
|
241
241
|
if (pkgFile[type] && pkgFile[type][slug] && pkgFile[type][slug] === versionNum) {
|
|
242
|
-
return
|
|
242
|
+
return this.log(`Package ${slug} version ${versionNum} is already a dependency`);
|
|
243
243
|
}
|
|
244
244
|
// Install dependency.
|
|
245
245
|
await manager.install(slug, version);
|
|
@@ -273,13 +273,13 @@ export class ManagerLocal extends Manager {
|
|
|
273
273
|
// Get package information from registry.
|
|
274
274
|
const pkg = this.getPackage(slug);
|
|
275
275
|
if (!pkg)
|
|
276
|
-
return
|
|
276
|
+
return this.log(`Package ${slug} not found in registry`);
|
|
277
277
|
const versionNum = version || pkg.latestVersion();
|
|
278
278
|
const pkgVersion = pkg?.getVersion(versionNum);
|
|
279
279
|
if (!pkgVersion)
|
|
280
|
-
return
|
|
280
|
+
return this.log(`Package ${slug} version ${versionNum} not found in registry`);
|
|
281
281
|
if (!pkgVersion.installed)
|
|
282
|
-
return
|
|
282
|
+
return this.log(`Package ${slug} version ${versionNum} not installed`);
|
|
283
283
|
// Elevate permissions if not running as admin.
|
|
284
284
|
if (!isAdmin() && !isTests()) {
|
|
285
285
|
let command = `--operation uninstall --type ${this.type} --slug ${slug}`;
|
|
@@ -312,9 +312,9 @@ export class ManagerLocal extends Manager {
|
|
|
312
312
|
// Get local package file.
|
|
313
313
|
const pkgFile = packageLoadFile(filePath);
|
|
314
314
|
if (!pkgFile[type])
|
|
315
|
-
return
|
|
315
|
+
return this.log(`Package ${type} is missing`);
|
|
316
316
|
if (!pkgFile[type][slug])
|
|
317
|
-
return
|
|
317
|
+
return this.log(`Package ${type} ${slug} is not a dependency`);
|
|
318
318
|
// Uninstall dependency.
|
|
319
319
|
const manager = new ManagerLocal(type, this.config.config);
|
|
320
320
|
await manager.sync();
|
package/build/classes/Package.js
CHANGED
|
@@ -10,7 +10,7 @@ export class Package extends Base {
|
|
|
10
10
|
constructor(slug, versions) {
|
|
11
11
|
super();
|
|
12
12
|
if (!isValidSlug(slug))
|
|
13
|
-
|
|
13
|
+
this.log('Invalid package slug', slug);
|
|
14
14
|
this.reports = new Map();
|
|
15
15
|
this.slug = slug;
|
|
16
16
|
this.versions = versions ? new Map(Object.entries(versions)) : new Map();
|
|
@@ -28,7 +28,7 @@ export class Package extends Base {
|
|
|
28
28
|
if (Object.keys(report).length > 0)
|
|
29
29
|
this.reports.set(num, report);
|
|
30
30
|
if (errors.length > 0) {
|
|
31
|
-
|
|
31
|
+
this.log(errors);
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
34
|
this.versions.set(num, version);
|
package/build/helpers/admin.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// npm run build && node ./build/helpers/admin.js --operation uninstall --type plugins --id surge-synthesizer/surge
|
|
4
4
|
import { ManagerLocal } from '../classes/ManagerLocal.js';
|
|
5
5
|
import { dirApp } from './file.js';
|
|
6
|
+
import { log } from './utils.js';
|
|
6
7
|
export function adminArguments() {
|
|
7
8
|
return {
|
|
8
9
|
operation: process.argv[3],
|
|
@@ -22,7 +23,7 @@ export async function adminInit() {
|
|
|
22
23
|
await manager.uninstall(argv.id, argv.ver);
|
|
23
24
|
}
|
|
24
25
|
else {
|
|
25
|
-
|
|
26
|
+
log('Missing --operation argument');
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
adminInit();
|
package/build/helpers/api.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
import { log } from './utils.js';
|
|
1
2
|
export async function apiBuffer(url) {
|
|
2
|
-
|
|
3
|
+
log('⤓', url);
|
|
3
4
|
return fetch(url).then((res) => res.arrayBuffer());
|
|
4
5
|
}
|
|
5
6
|
export async function apiJson(url) {
|
|
6
|
-
|
|
7
|
+
log('⤓', url);
|
|
7
8
|
return fetch(url).then((res) => res.json());
|
|
8
9
|
}
|
|
9
10
|
export async function apiText(url) {
|
|
10
|
-
|
|
11
|
+
log('⤓', url);
|
|
11
12
|
return fetch(url).then((res) => res.text());
|
|
12
13
|
}
|
package/build/helpers/file.js
CHANGED
|
@@ -15,8 +15,9 @@ import { SystemType } from '../types/SystemType.js';
|
|
|
15
15
|
import { fileURLToPath } from 'url';
|
|
16
16
|
import sudoPrompt from '@vscode/sudo-prompt';
|
|
17
17
|
import { getSystem } from './utilsLocal.js';
|
|
18
|
+
import { log } from './utils.js';
|
|
18
19
|
export async function archiveExtract(filePath, dirPath) {
|
|
19
|
-
|
|
20
|
+
log('⎋', dirPath);
|
|
20
21
|
const ext = path.extname(filePath).trim().toLowerCase();
|
|
21
22
|
if (ext === '.zip') {
|
|
22
23
|
const zip = new AdmZip(filePath);
|
|
@@ -47,7 +48,7 @@ export function dirContains(parentDir, childDir) {
|
|
|
47
48
|
}
|
|
48
49
|
export function dirCreate(dir) {
|
|
49
50
|
if (!dirExists(dir)) {
|
|
50
|
-
|
|
51
|
+
log('+', dir);
|
|
51
52
|
mkdirSync(dir, { recursive: true });
|
|
52
53
|
return dir;
|
|
53
54
|
}
|
|
@@ -55,7 +56,7 @@ export function dirCreate(dir) {
|
|
|
55
56
|
}
|
|
56
57
|
export function dirDelete(dir) {
|
|
57
58
|
if (dirExists(dir)) {
|
|
58
|
-
|
|
59
|
+
log('-', dir);
|
|
59
60
|
return rmSync(dir, { recursive: true });
|
|
60
61
|
}
|
|
61
62
|
return false;
|
|
@@ -72,8 +73,8 @@ export function dirIs(dir) {
|
|
|
72
73
|
}
|
|
73
74
|
export function dirMove(dir, dirNew) {
|
|
74
75
|
if (dirExists(dir)) {
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
log('-', dir);
|
|
77
|
+
log('+', dirNew);
|
|
77
78
|
return moveSync(dir, dirNew, { overwrite: true });
|
|
78
79
|
}
|
|
79
80
|
return false;
|
|
@@ -88,7 +89,7 @@ export function dirOpen(dir) {
|
|
|
88
89
|
command = 'open';
|
|
89
90
|
else
|
|
90
91
|
command = 'xdg-open';
|
|
91
|
-
|
|
92
|
+
log('⎋', `${command} "${dir}"`);
|
|
92
93
|
return execSync(`${command} "${dir}"`);
|
|
93
94
|
}
|
|
94
95
|
export function dirPackage(pkg) {
|
|
@@ -120,7 +121,7 @@ export function dirProjects() {
|
|
|
120
121
|
return path.join(os.homedir(), 'Documents', 'Audio');
|
|
121
122
|
}
|
|
122
123
|
export function dirRead(dir, options) {
|
|
123
|
-
|
|
124
|
+
log('⌕', dir);
|
|
124
125
|
// Glob now expects forward slashes on Windows
|
|
125
126
|
// Convert backslashes from path.join() to forwardslashes
|
|
126
127
|
if (getSystem() === SystemType.Win) {
|
|
@@ -135,7 +136,7 @@ export function dirRename(dir, dirNew) {
|
|
|
135
136
|
return false;
|
|
136
137
|
}
|
|
137
138
|
export function fileCreate(filePath, data) {
|
|
138
|
-
|
|
139
|
+
log('+', filePath);
|
|
139
140
|
return writeFileSync(filePath, data);
|
|
140
141
|
}
|
|
141
142
|
export function fileCreateJson(filePath, data) {
|
|
@@ -149,7 +150,7 @@ export function fileDate(filePath) {
|
|
|
149
150
|
}
|
|
150
151
|
export function fileDelete(filePath) {
|
|
151
152
|
if (fileExists(filePath)) {
|
|
152
|
-
|
|
153
|
+
log('-', filePath);
|
|
153
154
|
return unlinkSync(filePath);
|
|
154
155
|
}
|
|
155
156
|
return false;
|
|
@@ -161,7 +162,7 @@ export function fileExists(filePath) {
|
|
|
161
162
|
return existsSync(filePath);
|
|
162
163
|
}
|
|
163
164
|
export async function fileHash(filePath, algorithm = 'sha256') {
|
|
164
|
-
|
|
165
|
+
log('⎋', filePath);
|
|
165
166
|
const input = createReadStream(filePath);
|
|
166
167
|
const hash = createHash(algorithm);
|
|
167
168
|
await stream.pipeline(input, hash);
|
|
@@ -194,13 +195,13 @@ export function fileInstall(filePath) {
|
|
|
194
195
|
default:
|
|
195
196
|
throw new Error(`Unsupported file format: ${ext}`);
|
|
196
197
|
}
|
|
197
|
-
|
|
198
|
+
log('⎋', command);
|
|
198
199
|
return execSync(command, { stdio: 'inherit' });
|
|
199
200
|
}
|
|
200
201
|
export function fileMove(filePath, newPath) {
|
|
201
202
|
if (fileExists(filePath)) {
|
|
202
|
-
|
|
203
|
-
|
|
203
|
+
log('-', filePath);
|
|
204
|
+
log('+', newPath);
|
|
204
205
|
return moveSync(filePath, newPath, { overwrite: true });
|
|
205
206
|
}
|
|
206
207
|
return false;
|
|
@@ -217,10 +218,10 @@ export function filesMove(dirSource, dirTarget, dirSub, formatDir) {
|
|
|
217
218
|
const fileExtTarget = formatDir[fileExt];
|
|
218
219
|
// If this is not a supported file format, then ignore.
|
|
219
220
|
if (fileExtTarget === undefined)
|
|
220
|
-
return
|
|
221
|
+
return log(`${fileSource} - ${fileExt} not mapped to a installation folder, skipping.`);
|
|
221
222
|
const fileTarget = path.join(dirTarget, fileExtTarget, dirSub, path.basename(fileSource));
|
|
222
223
|
if (fileExists(fileTarget))
|
|
223
|
-
return
|
|
224
|
+
return log(`${fileSource} - ${fileTarget} already exists, skipping.`);
|
|
224
225
|
dirCreate(path.dirname(fileTarget));
|
|
225
226
|
fileMove(fileSource, fileTarget);
|
|
226
227
|
filesMoved.push(fileTarget);
|
|
@@ -237,22 +238,22 @@ export function fileOpen(filePath) {
|
|
|
237
238
|
command = 'open';
|
|
238
239
|
else
|
|
239
240
|
command = 'xdg-open';
|
|
240
|
-
|
|
241
|
+
log('⎋', `${command} "${filePath}"`);
|
|
241
242
|
return execSync(`${command} "${filePath}"`);
|
|
242
243
|
}
|
|
243
244
|
export function fileRead(filePath) {
|
|
244
|
-
|
|
245
|
+
log('⎋', filePath);
|
|
245
246
|
return readFileSync(filePath, 'utf8');
|
|
246
247
|
}
|
|
247
248
|
export function fileReadJson(filePath) {
|
|
248
249
|
if (fileExists(filePath)) {
|
|
249
|
-
|
|
250
|
+
log('⎋', filePath);
|
|
250
251
|
return JSON.parse(readFileSync(filePath, 'utf8').toString());
|
|
251
252
|
}
|
|
252
253
|
return false;
|
|
253
254
|
}
|
|
254
255
|
export function fileReadString(filePath) {
|
|
255
|
-
|
|
256
|
+
log('⎋', filePath);
|
|
256
257
|
return readFileSync(filePath, 'utf8').toString();
|
|
257
258
|
}
|
|
258
259
|
export function fileReadYaml(filePath) {
|
|
@@ -313,10 +314,10 @@ export function runCliAsAdmin(args) {
|
|
|
313
314
|
const script = path.join(dirPathClean, 'admin.js');
|
|
314
315
|
sudoPrompt.exec(`node "${script}" ${args}`, { name: 'Open Audio Stack' }, (error, stdout, stderr) => {
|
|
315
316
|
if (stdout) {
|
|
316
|
-
|
|
317
|
+
log('runCliAsAdmin', stdout);
|
|
317
318
|
}
|
|
318
319
|
if (stderr) {
|
|
319
|
-
|
|
320
|
+
log('runCliAsAdmin', stderr);
|
|
320
321
|
}
|
|
321
322
|
if (error) {
|
|
322
323
|
reject(error);
|
|
@@ -334,7 +335,7 @@ export function zipCreate(filesPath, zipPath) {
|
|
|
334
335
|
const zip = new AdmZip();
|
|
335
336
|
const pathList = dirRead(filesPath);
|
|
336
337
|
pathList.forEach(pathItem => {
|
|
337
|
-
|
|
338
|
+
log('⎋', pathItem);
|
|
338
339
|
try {
|
|
339
340
|
if (dirIs(pathItem)) {
|
|
340
341
|
zip.addLocalFolder(pathItem, path.basename(pathItem));
|
|
@@ -344,9 +345,9 @@ export function zipCreate(filesPath, zipPath) {
|
|
|
344
345
|
}
|
|
345
346
|
}
|
|
346
347
|
catch (error) {
|
|
347
|
-
|
|
348
|
+
log(error);
|
|
348
349
|
}
|
|
349
350
|
});
|
|
350
|
-
|
|
351
|
+
log('+', zipPath);
|
|
351
352
|
return zip.writeZip(zipPath);
|
|
352
353
|
}
|
|
@@ -87,7 +87,6 @@ export declare const PackageTypeObj: {
|
|
|
87
87
|
Effect: PluginType.Effect;
|
|
88
88
|
Generator: PluginType.Generator;
|
|
89
89
|
Instrument: PluginType.Instrument;
|
|
90
|
-
Preset: PluginType.Preset;
|
|
91
90
|
Sampler: PluginType.Sampler;
|
|
92
91
|
Tool: PluginType.Tool;
|
|
93
92
|
};
|
|
@@ -160,7 +159,6 @@ export declare const PackageVersionValidator: z.ZodObject<{
|
|
|
160
159
|
Effect: PluginType.Effect;
|
|
161
160
|
Generator: PluginType.Generator;
|
|
162
161
|
Instrument: PluginType.Instrument;
|
|
163
|
-
Preset: PluginType.Preset;
|
|
164
162
|
Sampler: PluginType.Sampler;
|
|
165
163
|
Tool: PluginType.Tool;
|
|
166
164
|
}>;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import { fileCreateJson, fileReadJson } from './file.js';
|
|
3
3
|
import { Package } from '../classes/Package.js';
|
|
4
|
-
import { pathGetSlug, pathGetVersion } from './utils.js';
|
|
4
|
+
import { log, pathGetSlug, pathGetVersion } from './utils.js';
|
|
5
5
|
export function packageLoadFile(filePath) {
|
|
6
6
|
// Read the file path and parse as json.
|
|
7
7
|
if (!filePath)
|
|
8
8
|
filePath = path.join('.', 'index.json');
|
|
9
9
|
const pkgFile = fileReadJson(filePath);
|
|
10
10
|
if (!pkgFile)
|
|
11
|
-
|
|
11
|
+
log(filePath, `not a valid json file`);
|
|
12
12
|
// Validate package json file structure, fields and values.
|
|
13
13
|
const pkg = new Package(pathGetSlug(filePath));
|
|
14
14
|
pkg.addVersion(pathGetVersion(filePath), pkgFile);
|
|
15
|
-
|
|
15
|
+
log(JSON.stringify(pkg.getReport()));
|
|
16
16
|
return pkgFile;
|
|
17
17
|
}
|
|
18
18
|
export function packageSaveFile(pkgFile, filePath) {
|
package/build/helpers/utils.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export declare function inputGetParts(input: string): string[];
|
|
2
|
+
export declare function log(...args: any): void;
|
|
3
|
+
export declare function logEnable(): boolean;
|
|
4
|
+
export declare function logDisable(): boolean;
|
|
2
5
|
export declare function pathGetDirectory(path: string, sep?: string): string;
|
|
3
6
|
export declare function pathGetExt(path: string, sep?: string): string;
|
|
4
7
|
export declare function pathGetFilename(path: string, sep?: string): string;
|
package/build/helpers/utils.js
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import * as semver from 'semver';
|
|
2
2
|
import slugify from 'slugify';
|
|
3
|
+
let DEBUG = false;
|
|
3
4
|
const URLSAFE_REGEX = /[^\w\s$*_+~.()'"!\-:@/]+/g;
|
|
4
5
|
export function inputGetParts(input) {
|
|
5
6
|
return input.split('@');
|
|
6
7
|
}
|
|
8
|
+
export function log(...args) {
|
|
9
|
+
if (DEBUG)
|
|
10
|
+
console.log(...args);
|
|
11
|
+
}
|
|
12
|
+
export function logEnable() {
|
|
13
|
+
return (DEBUG = true);
|
|
14
|
+
}
|
|
15
|
+
export function logDisable() {
|
|
16
|
+
return (DEBUG = false);
|
|
17
|
+
}
|
|
7
18
|
export function pathGetDirectory(path, sep = '/') {
|
|
8
19
|
return path.substring(0, path.lastIndexOf(sep));
|
|
9
20
|
}
|
|
@@ -3,7 +3,6 @@ export var PluginType;
|
|
|
3
3
|
PluginType["Effect"] = "effect";
|
|
4
4
|
PluginType["Generator"] = "generator";
|
|
5
5
|
PluginType["Instrument"] = "instrument";
|
|
6
|
-
PluginType["Preset"] = "preset";
|
|
7
6
|
PluginType["Sampler"] = "sampler";
|
|
8
7
|
PluginType["Tool"] = "tool";
|
|
9
8
|
})(PluginType || (PluginType = {}));
|
|
@@ -23,11 +22,6 @@ export const pluginTypes = [
|
|
|
23
22
|
value: PluginType.Instrument,
|
|
24
23
|
name: 'Instrument',
|
|
25
24
|
},
|
|
26
|
-
{
|
|
27
|
-
description: 'Preset containing predefined settings for an instrument or effect.',
|
|
28
|
-
value: PluginType.Preset,
|
|
29
|
-
name: 'Preset',
|
|
30
|
-
},
|
|
31
25
|
{
|
|
32
26
|
description: 'Sample playback based on audio or midi input.',
|
|
33
27
|
value: PluginType.Sampler,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-audio-stack/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18",
|
|
4
4
|
"description": "Open-source audio plugin management software",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./build/index.js",
|
|
@@ -44,14 +44,14 @@
|
|
|
44
44
|
"@types/js-yaml": "^4.0.9",
|
|
45
45
|
"@types/node": "^22.7.8",
|
|
46
46
|
"@types/semver": "^7.5.8",
|
|
47
|
-
"@vitest/coverage-v8": "^
|
|
47
|
+
"@vitest/coverage-v8": "^3.0.5",
|
|
48
48
|
"eslint": "^9.12.0",
|
|
49
49
|
"globals": "^15.2.0",
|
|
50
50
|
"prettier": "^3.2.5",
|
|
51
|
-
"tsx": "^4.
|
|
51
|
+
"tsx": "^4.19.2",
|
|
52
52
|
"typescript": "^5.6.3",
|
|
53
53
|
"typescript-eslint": "^8.9.0",
|
|
54
|
-
"vitest": "^
|
|
54
|
+
"vitest": "^3.0.5"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
57
|
"@vscode/sudo-prompt": "^9.3.1",
|