@open-audio-stack/core 0.1.37 → 0.1.39
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/ManagerLocal.d.ts +2 -1
- package/build/classes/ManagerLocal.js +64 -9
- package/build/helpers/admin.js +1 -0
- package/build/helpers/configLocal.js +2 -1
- package/build/helpers/file.d.ts +4 -3
- package/build/helpers/file.js +41 -11
- package/build/types/Config.d.ts +1 -0
- package/build/types/Registry.d.ts +2 -0
- package/build/types/Registry.js +1 -0
- package/package.json +3 -3
|
@@ -6,6 +6,7 @@ import { ConfigInterface } from '../types/Config.js';
|
|
|
6
6
|
export declare class ManagerLocal extends Manager {
|
|
7
7
|
protected typeDir: string;
|
|
8
8
|
constructor(type: RegistryType, config?: ConfigInterface);
|
|
9
|
+
isPackageInstalled(slug: string, version: string): boolean;
|
|
9
10
|
create(): Promise<void>;
|
|
10
11
|
scan(ext?: string, installable?: boolean): void;
|
|
11
12
|
export(dir: string, ext?: string): boolean;
|
|
@@ -13,7 +14,7 @@ export declare class ManagerLocal extends Manager {
|
|
|
13
14
|
installAll(): Promise<Package[]>;
|
|
14
15
|
installDependency(slug: string, version?: string, filePath?: string, type?: RegistryType): Promise<any>;
|
|
15
16
|
installDependencies(filePath: string, type?: RegistryType): Promise<any>;
|
|
16
|
-
open(
|
|
17
|
+
open(slug: string, version?: string, options?: string[]): boolean;
|
|
17
18
|
uninstall(slug: string, version?: string): Promise<void | PackageVersion>;
|
|
18
19
|
uninstallDependency(slug: string, version?: string, filePath?: string, type?: RegistryType): Promise<any>;
|
|
19
20
|
uninstallDependencies(filePath?: string, type?: RegistryType): Promise<any>;
|
|
@@ -27,6 +27,10 @@ export class ManagerLocal extends Manager {
|
|
|
27
27
|
this.config = new ConfigLocal(config);
|
|
28
28
|
this.typeDir = this.config.get(`${type}Dir`);
|
|
29
29
|
}
|
|
30
|
+
isPackageInstalled(slug, version) {
|
|
31
|
+
const versionDirs = dirRead(path.join(this.typeDir, '**', slug, version));
|
|
32
|
+
return versionDirs.length > 0;
|
|
33
|
+
}
|
|
30
34
|
async create() {
|
|
31
35
|
// TODO Rewrite this code after prototype is proven.
|
|
32
36
|
const pkgQuestions = [
|
|
@@ -165,8 +169,9 @@ export class ManagerLocal extends Manager {
|
|
|
165
169
|
const pkgVersion = pkg?.getVersion(versionNum);
|
|
166
170
|
if (!pkgVersion)
|
|
167
171
|
return this.log(`Package ${slug} version ${versionNum} not found in registry`);
|
|
168
|
-
if (
|
|
172
|
+
if (this.isPackageInstalled(slug, versionNum)) {
|
|
169
173
|
this.log(`Package ${slug} version ${versionNum} already installed`);
|
|
174
|
+
pkgVersion.installed = true;
|
|
170
175
|
return pkgVersion;
|
|
171
176
|
}
|
|
172
177
|
// Elevate permissions if not running as admin.
|
|
@@ -177,7 +182,14 @@ export class ManagerLocal extends Manager {
|
|
|
177
182
|
if (this.debug)
|
|
178
183
|
command += ` --log`;
|
|
179
184
|
await runCliAsAdmin(command);
|
|
180
|
-
|
|
185
|
+
const returnedPkg = this.getPackage(slug)?.getVersion(versionNum);
|
|
186
|
+
if (returnedPkg) {
|
|
187
|
+
if (this.isPackageInstalled(slug, versionNum))
|
|
188
|
+
returnedPkg.installed = true;
|
|
189
|
+
else
|
|
190
|
+
delete returnedPkg.installed;
|
|
191
|
+
return returnedPkg;
|
|
192
|
+
}
|
|
181
193
|
}
|
|
182
194
|
// Create temporary directory to store downloaded files.
|
|
183
195
|
const dirDownloads = path.join(this.config.get('appDir'), 'downloads', this.type, slug, versionNum);
|
|
@@ -305,11 +317,47 @@ export class ManagerLocal extends Manager {
|
|
|
305
317
|
pkgFile.installed = true;
|
|
306
318
|
return pkgFile;
|
|
307
319
|
}
|
|
308
|
-
open(
|
|
309
|
-
|
|
310
|
-
//
|
|
311
|
-
|
|
312
|
-
|
|
320
|
+
open(slug, version, options = []) {
|
|
321
|
+
this.log('open', slug, version, options);
|
|
322
|
+
// Get package information
|
|
323
|
+
const pkg = this.getPackage(slug);
|
|
324
|
+
if (!pkg) {
|
|
325
|
+
this.log(`Package ${slug} not found`);
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
const versionNum = version || pkg.latestVersion();
|
|
329
|
+
const pkgVersion = pkg.getVersion(versionNum);
|
|
330
|
+
if (!pkgVersion) {
|
|
331
|
+
this.log(`Package ${slug} version ${versionNum} not found`);
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
// Check if package has open field
|
|
335
|
+
if (!pkgVersion.open) {
|
|
336
|
+
this.log(`Package ${slug} has no open command defined`);
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
// Check if package is installed
|
|
340
|
+
if (!this.isPackageInstalled(slug, versionNum)) {
|
|
341
|
+
this.log(`Package ${slug} version ${versionNum} not installed`);
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
try {
|
|
345
|
+
const openPath = pkgVersion.open;
|
|
346
|
+
const packageDir = path.join(this.typeDir, slug, versionNum);
|
|
347
|
+
const fullPath = path.isAbsolute(openPath) ? openPath : path.join(packageDir, openPath);
|
|
348
|
+
const command = `"${fullPath}" ${options.join(' ')}`;
|
|
349
|
+
this.log(`Running: ${command}`);
|
|
350
|
+
if (isTests()) {
|
|
351
|
+
this.log(`Would run: ${command}`);
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
fileOpen(fullPath);
|
|
355
|
+
}
|
|
356
|
+
return true;
|
|
357
|
+
}
|
|
358
|
+
catch (error) {
|
|
359
|
+
this.log(`Error opening package ${slug}:`, error);
|
|
360
|
+
return false;
|
|
313
361
|
}
|
|
314
362
|
}
|
|
315
363
|
async uninstall(slug, version) {
|
|
@@ -321,7 +369,7 @@ export class ManagerLocal extends Manager {
|
|
|
321
369
|
const pkgVersion = pkg?.getVersion(versionNum);
|
|
322
370
|
if (!pkgVersion)
|
|
323
371
|
return this.log(`Package ${slug} version ${versionNum} not found in registry`);
|
|
324
|
-
if (!
|
|
372
|
+
if (!this.isPackageInstalled(slug, versionNum))
|
|
325
373
|
return this.log(`Package ${slug} version ${versionNum} not installed`);
|
|
326
374
|
// Elevate permissions if not running as admin.
|
|
327
375
|
if (!isAdmin() && !isTests()) {
|
|
@@ -331,7 +379,14 @@ export class ManagerLocal extends Manager {
|
|
|
331
379
|
if (this.debug)
|
|
332
380
|
command += ` --log`;
|
|
333
381
|
await runCliAsAdmin(command);
|
|
334
|
-
|
|
382
|
+
const returnedPkg = this.getPackage(slug)?.getVersion(versionNum);
|
|
383
|
+
if (returnedPkg) {
|
|
384
|
+
if (this.isPackageInstalled(slug, versionNum))
|
|
385
|
+
returnedPkg.installed = true;
|
|
386
|
+
else
|
|
387
|
+
delete returnedPkg.installed;
|
|
388
|
+
return returnedPkg;
|
|
389
|
+
}
|
|
335
390
|
}
|
|
336
391
|
// Delete all directories for this package version.
|
|
337
392
|
const versionDirs = dirRead(path.join(this.typeDir, '**', slug, versionNum));
|
package/build/helpers/admin.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { configDefaults } from './config.js';
|
|
2
|
-
import { dirApp, dirPlugins, dirPresets, dirProjects } from './file.js';
|
|
2
|
+
import { dirApp, dirApps, dirPlugins, dirPresets, dirProjects } from './file.js';
|
|
3
3
|
export function configDefaultsLocal() {
|
|
4
4
|
return {
|
|
5
5
|
...configDefaults(),
|
|
6
6
|
appDir: dirApp(),
|
|
7
|
+
appsDir: dirApps(),
|
|
7
8
|
pluginsDir: dirPlugins(),
|
|
8
9
|
presetsDir: dirPresets(),
|
|
9
10
|
projectsDir: dirProjects(),
|
package/build/helpers/file.d.ts
CHANGED
|
@@ -14,11 +14,12 @@ export declare function dirEmpty(dir: string): boolean;
|
|
|
14
14
|
export declare function dirExists(dir: string): boolean;
|
|
15
15
|
export declare function dirIs(dir: string): boolean;
|
|
16
16
|
export declare function dirMove(dir: string, dirNew: string): void | boolean;
|
|
17
|
-
export declare function dirOpen(dir: string): Buffer
|
|
17
|
+
export declare function dirOpen(dir: string): Buffer<ArrayBufferLike>;
|
|
18
18
|
export declare function dirPackage(pkg: PackageInterface): string;
|
|
19
19
|
export declare function dirPlugins(): string;
|
|
20
20
|
export declare function dirPresets(): string;
|
|
21
21
|
export declare function dirProjects(): string;
|
|
22
|
+
export declare function dirApps(): string;
|
|
22
23
|
export declare function dirRead(dir: string, options?: GlobOptionsWithFileTypesFalse): string[];
|
|
23
24
|
export declare function dirRename(dir: string, dirNew: string): void | boolean;
|
|
24
25
|
export declare function fileCreate(filePath: string, data: string | Buffer): void;
|
|
@@ -29,10 +30,10 @@ export declare function fileDelete(filePath: string): boolean | void;
|
|
|
29
30
|
export declare function fileExec(filePath: string): void;
|
|
30
31
|
export declare function fileExists(filePath: string): boolean;
|
|
31
32
|
export declare function fileHash(filePath: string, algorithm?: string): Promise<string>;
|
|
32
|
-
export declare function fileInstall(filePath: string): Buffer
|
|
33
|
+
export declare function fileInstall(filePath: string): Buffer<ArrayBufferLike>;
|
|
33
34
|
export declare function fileMove(filePath: string, newPath: string): void | boolean;
|
|
34
35
|
export declare function filesMove(dirSource: string, dirTarget: string, dirSub: string, formatDir: Record<string, string>): string[];
|
|
35
|
-
export declare function fileOpen(filePath: string): Buffer
|
|
36
|
+
export declare function fileOpen(filePath: string): Buffer<ArrayBufferLike>;
|
|
36
37
|
export declare function fileRead(filePath: string): string;
|
|
37
38
|
export declare function fileReadJson(filePath: string): any;
|
|
38
39
|
export declare function fileReadString(filePath: string): string;
|
package/build/helpers/file.js
CHANGED
|
@@ -21,7 +21,28 @@ export async function archiveExtract(filePath, dirPath) {
|
|
|
21
21
|
const ext = path.extname(filePath).trim().toLowerCase();
|
|
22
22
|
if (ext === '.zip') {
|
|
23
23
|
const zip = new AdmZip(filePath);
|
|
24
|
-
|
|
24
|
+
try {
|
|
25
|
+
return zip.extractAllTo(dirPath);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
// Handle Windows special character issues by extracting files manually
|
|
29
|
+
if (getSystem() === SystemType.Win && error.message?.includes('ENOENT')) {
|
|
30
|
+
log('⚠️', 'Extracting files manually due to special characters in filenames');
|
|
31
|
+
const entries = zip.getEntries();
|
|
32
|
+
entries.forEach(entry => {
|
|
33
|
+
const sanitizedName = entry.entryName.replace(/[<>:"|?*]/g, '_').replace(/[\r\n]/g, '');
|
|
34
|
+
if (!entry.isDirectory) {
|
|
35
|
+
const outputPath = path.join(dirPath, sanitizedName);
|
|
36
|
+
dirCreate(path.dirname(outputPath));
|
|
37
|
+
writeFileSync(outputPath, entry.getData());
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
dirCreate(path.join(dirPath, sanitizedName));
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
25
46
|
}
|
|
26
47
|
else if (ext === '.tar' || ext === '.gz' || ext === '.tgz') {
|
|
27
48
|
return await tar.extract({
|
|
@@ -120,6 +141,13 @@ export function dirProjects() {
|
|
|
120
141
|
return path.join(os.homedir(), 'Documents', 'Audio');
|
|
121
142
|
return path.join(os.homedir(), 'Documents', 'Audio');
|
|
122
143
|
}
|
|
144
|
+
export function dirApps() {
|
|
145
|
+
if (getSystem() === SystemType.Win)
|
|
146
|
+
return path.join(os.homedir(), 'AppData', 'Local', 'Programs');
|
|
147
|
+
else if (getSystem() === SystemType.Mac)
|
|
148
|
+
return path.join('/Applications');
|
|
149
|
+
return path.join('/usr', 'local', 'bin');
|
|
150
|
+
}
|
|
123
151
|
export function dirRead(dir, options) {
|
|
124
152
|
log('⌕', dir);
|
|
125
153
|
// Glob now expects forward slashes on Windows
|
|
@@ -326,22 +354,24 @@ export function runCliAsAdmin(args) {
|
|
|
326
354
|
const logFile = path.join(dirPathClean, 'admin.log');
|
|
327
355
|
writeFileSync(logFile, ''); // Clear previous logs
|
|
328
356
|
log(`Running as admin: node "${script}" ${args}`);
|
|
329
|
-
//
|
|
357
|
+
// Monitor log file for completion
|
|
358
|
+
let completed = false;
|
|
330
359
|
const tail = spawn('tail', ['-f', logFile]);
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
360
|
+
tail.stdout.on('data', data => {
|
|
361
|
+
const output = data.toString();
|
|
362
|
+
log(output);
|
|
363
|
+
if (output.includes('ADMIN_COMPLETE')) {
|
|
364
|
+
completed = true;
|
|
365
|
+
tail.kill();
|
|
366
|
+
resolve();
|
|
367
|
+
}
|
|
335
368
|
});
|
|
336
369
|
// Run the script with sudoPrompt
|
|
337
370
|
sudoPrompt.exec(`node "${script}" ${args} >> "${logFile}" 2>&1`, { name: 'Open Audio Stack' }, error => {
|
|
338
|
-
|
|
339
|
-
|
|
371
|
+
if (error && !completed) {
|
|
372
|
+
tail.kill();
|
|
340
373
|
reject(error);
|
|
341
374
|
}
|
|
342
|
-
else {
|
|
343
|
-
resolve();
|
|
344
|
-
}
|
|
345
375
|
});
|
|
346
376
|
});
|
|
347
377
|
}
|
package/build/types/Config.d.ts
CHANGED
|
@@ -3,11 +3,13 @@ export interface RegistryInterface {
|
|
|
3
3
|
name: string;
|
|
4
4
|
url: string;
|
|
5
5
|
version: string;
|
|
6
|
+
[RegistryType.Apps]?: RegistryPackages;
|
|
6
7
|
[RegistryType.Plugins]?: RegistryPackages;
|
|
7
8
|
[RegistryType.Presets]?: RegistryPackages;
|
|
8
9
|
[RegistryType.Projects]?: RegistryPackages;
|
|
9
10
|
}
|
|
10
11
|
export declare enum RegistryType {
|
|
12
|
+
Apps = "apps",
|
|
11
13
|
Plugins = "plugins",
|
|
12
14
|
Presets = "presets",
|
|
13
15
|
Projects = "projects"
|
package/build/types/Registry.js
CHANGED
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.39",
|
|
4
4
|
"description": "Open-source audio plugin management software",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./build/index.js",
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"globals": "^15.2.0",
|
|
50
50
|
"prettier": "^3.2.5",
|
|
51
51
|
"tsx": "^4.19.2",
|
|
52
|
-
"typescript": "^5.
|
|
53
|
-
"typescript-eslint": "^8.
|
|
52
|
+
"typescript": "^5.9.3",
|
|
53
|
+
"typescript-eslint": "^8.48.0",
|
|
54
54
|
"vitest": "^3.0.5"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|