@open-audio-stack/core 0.1.42 → 0.1.43

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.
@@ -14,7 +14,7 @@ export declare class Manager extends Base {
14
14
  getPackage(slug: string): Package | undefined;
15
15
  getReport(): ManagerReport;
16
16
  outputReport(): void;
17
- listPackages(installed?: boolean): Package[];
17
+ listPackages(installed?: boolean, showAll?: boolean): Package[];
18
18
  removePackage(slug: string): void;
19
19
  reset(): void;
20
20
  search(query: string): Package[];
@@ -2,6 +2,8 @@ import { apiJson } from '../helpers/api.js';
2
2
  import { Config } from './Config.js';
3
3
  import { Package } from './Package.js';
4
4
  import { Base } from './Base.js';
5
+ import { packageCompatibleFiles } from '../helpers/package.js';
6
+ import { getArchitecture, getSystem } from '../helpers/utilsLocal.js';
5
7
  export class Manager extends Base {
6
8
  config;
7
9
  packages;
@@ -52,19 +54,21 @@ export class Manager extends Base {
52
54
  }
53
55
  }
54
56
  }
55
- listPackages(installed) {
57
+ listPackages(installed, showAll = false) {
58
+ let packages = Array.from(this.packages.values());
56
59
  if (installed !== undefined) {
57
- const packagesFiltered = [];
58
- Array.from(this.packages.values()).forEach(pkg => {
59
- Array.from(pkg.versions.values()).forEach(pkgVersion => {
60
- if ((installed === true && pkgVersion.installed) || (installed === false && !pkgVersion.installed)) {
61
- packagesFiltered.push(pkg);
62
- }
63
- });
60
+ packages = packages.filter(pkg => Array.from(pkg.versions.values()).some(pkgVersion => (installed === true && pkgVersion.installed) || (installed === false && !pkgVersion.installed)));
61
+ }
62
+ if (!showAll) {
63
+ packages = packages.filter(pkg => {
64
+ const pkgVersion = pkg.getVersionLatest();
65
+ if (!pkgVersion)
66
+ return false;
67
+ const files = packageCompatibleFiles(pkgVersion, [getArchitecture()], [getSystem()], []);
68
+ return files.length > 0;
64
69
  });
65
- return packagesFiltered;
66
70
  }
67
- return Array.from(this.packages.values());
71
+ return packages.sort((a, b) => a.slug.localeCompare(b.slug));
68
72
  }
69
73
  removePackage(slug) {
70
74
  if (!this.packages.has(slug))
@@ -10,12 +10,12 @@ export declare class ManagerLocal extends Manager {
10
10
  create(): Promise<void>;
11
11
  scan(ext?: string, installable?: boolean): void;
12
12
  export(dir: string, ext?: string): boolean;
13
- install(slug: string, version?: string): Promise<void | PackageVersion>;
13
+ install(slug: string, version?: string): Promise<PackageVersion>;
14
14
  installAll(): Promise<Package[]>;
15
15
  installDependency(slug: string, version?: string, filePath?: string, type?: RegistryType): Promise<any>;
16
16
  installDependencies(filePath: string, type?: RegistryType): Promise<any>;
17
17
  open(slug: string, version?: string, options?: string[]): boolean;
18
- uninstall(slug: string, version?: string): Promise<void | PackageVersion>;
18
+ uninstall(slug: string, version?: string): Promise<PackageVersion>;
19
19
  uninstallDependency(slug: string, version?: string, filePath?: string, type?: RegistryType): Promise<any>;
20
20
  uninstallDependencies(filePath?: string, type?: RegistryType): Promise<any>;
21
21
  }
@@ -164,16 +164,28 @@ export class ManagerLocal extends Manager {
164
164
  // Get package information from registry.
165
165
  const pkg = this.getPackage(slug);
166
166
  if (!pkg)
167
- return this.log(`Package ${slug} not found in registry`);
167
+ throw new Error(`Package ${slug} not found in registry`);
168
168
  const versionNum = version || pkg.latestVersion();
169
169
  const pkgVersion = pkg?.getVersion(versionNum);
170
170
  if (!pkgVersion)
171
- return this.log(`Package ${slug} version ${versionNum} not found in registry`);
171
+ throw new Error(`Package ${slug} version ${versionNum} not found in registry`);
172
172
  if (this.isPackageInstalled(slug, versionNum)) {
173
173
  this.log(`Package ${slug} version ${versionNum} already installed`);
174
174
  pkgVersion.installed = true;
175
175
  return pkgVersion;
176
176
  }
177
+ // Check for compatible files before running admin command
178
+ const excludedFormats = [];
179
+ const system = getSystem();
180
+ if (system === SystemType.Linux) {
181
+ if (!(await commandExists('dpkg')))
182
+ excludedFormats.push(FileFormat.DebianPackage);
183
+ if (!(await commandExists('rpm')))
184
+ excludedFormats.push(FileFormat.RedHatPackage);
185
+ }
186
+ const files = packageCompatibleFiles(pkgVersion, [getArchitecture()], [getSystem()], excludedFormats);
187
+ if (!files.length)
188
+ throw new Error(`No compatible files found for ${slug}`);
177
189
  // Elevate permissions if not running as admin.
178
190
  if (!isAdmin() && !isTests()) {
179
191
  let command = `--appDir "${this.config.get('appDir')}" --operation "install" --type "${this.type}" --id "${slug}"`;
@@ -194,19 +206,6 @@ export class ManagerLocal extends Manager {
194
206
  // Create temporary directory to store downloaded files.
195
207
  const dirDownloads = path.join(this.config.get('appDir'), 'downloads', this.type, slug, versionNum);
196
208
  dirCreate(dirDownloads);
197
- // Not all Linux distributions support all file formats.
198
- const excludedFormats = [];
199
- const system = getSystem();
200
- if (system === SystemType.Linux) {
201
- if (!(await commandExists('dpkg')))
202
- excludedFormats.push(FileFormat.DebianPackage);
203
- if (!(await commandExists('rpm')))
204
- excludedFormats.push(FileFormat.RedHatPackage);
205
- }
206
- // Filter for compatible files and download.
207
- const files = packageCompatibleFiles(pkgVersion, [getArchitecture()], [getSystem()], excludedFormats);
208
- if (!files.length)
209
- return this.log(`Error: No compatible files found for ${slug}`);
210
209
  for (const key in files) {
211
210
  // Download file to temporary directory if not already downloaded.
212
211
  const file = files[key];
@@ -218,9 +217,10 @@ export class ManagerLocal extends Manager {
218
217
  // Check file hash matches expected hash.
219
218
  const hash = await fileHash(filePath);
220
219
  if (hash !== file.sha256)
221
- return this.log(`Error: ${filePath} hash mismatch`);
220
+ throw new Error(`${filePath} hash mismatch`);
222
221
  // If installer, run the installer headless (without the user interface).
223
222
  if (file.type === FileType.Installer) {
223
+ // Test time out if installing during tests.
224
224
  if (isTests())
225
225
  fileOpen(filePath);
226
226
  else
@@ -324,26 +324,22 @@ export class ManagerLocal extends Manager {
324
324
  // Get package information
325
325
  const pkg = this.getPackage(slug);
326
326
  if (!pkg) {
327
- this.log(`Package ${slug} not found`);
328
- return false;
327
+ throw new Error(`Package ${slug} not found`);
329
328
  }
330
329
  const versionNum = version || pkg.latestVersion();
331
330
  const pkgVersion = pkg.getVersion(versionNum);
332
331
  if (!pkgVersion) {
333
- this.log(`Package ${slug} version ${versionNum} not found`);
334
- return false;
332
+ throw new Error(`Package ${slug} version ${versionNum} not found`);
335
333
  }
336
334
  // Check if package is installed
337
335
  if (!this.isPackageInstalled(slug, versionNum)) {
338
- this.log(`Package ${slug} version ${versionNum} not installed`);
339
- return false;
336
+ throw new Error(`Package ${slug} version ${versionNum} not installed`);
340
337
  }
341
338
  // Filter compatible files and find one with open field
342
339
  const files = packageCompatibleFiles(pkgVersion, [getArchitecture()], [getSystem()], []);
343
340
  const openableFile = files.find(file => file.open);
344
341
  if (!openableFile) {
345
- this.log(`Package ${slug} has no compatible file with open command defined`);
346
- return false;
342
+ throw new Error(`Package ${slug} has no compatible file with open command defined`);
347
343
  }
348
344
  try {
349
345
  const openPath = openableFile.open;
@@ -370,12 +366,7 @@ export class ManagerLocal extends Manager {
370
366
  }
371
367
  const command = `"${fullPath}" ${options.join(' ')}`;
372
368
  this.log(`Running: ${command}`);
373
- if (isTests()) {
374
- this.log(`Would run: ${command}`);
375
- }
376
- else {
377
- fileOpen(fullPath);
378
- }
369
+ fileOpen(fullPath, options);
379
370
  return true;
380
371
  }
381
372
  catch (error) {
@@ -387,13 +378,13 @@ export class ManagerLocal extends Manager {
387
378
  // Get package information from registry.
388
379
  const pkg = this.getPackage(slug);
389
380
  if (!pkg)
390
- return this.log(`Package ${slug} not found in registry`);
381
+ throw new Error(`Package ${slug} not found in registry`);
391
382
  const versionNum = version || pkg.latestVersion();
392
383
  const pkgVersion = pkg?.getVersion(versionNum);
393
384
  if (!pkgVersion)
394
- return this.log(`Package ${slug} version ${versionNum} not found in registry`);
385
+ throw new Error(`Package ${slug} version ${versionNum} not found in registry`);
395
386
  if (!this.isPackageInstalled(slug, versionNum))
396
- return this.log(`Package ${slug} version ${versionNum} not installed`);
387
+ throw new Error(`Package ${slug} version ${versionNum} not installed`);
397
388
  // Elevate permissions if not running as admin.
398
389
  if (!isAdmin() && !isTests()) {
399
390
  let command = `--appDir "${this.config.get('appDir')}" --operation "uninstall" --type "${this.type}" --id "${slug}"`;
@@ -33,7 +33,7 @@ export declare function fileHash(filePath: string, algorithm?: string): Promise<
33
33
  export declare function fileInstall(filePath: string): Buffer<ArrayBufferLike>;
34
34
  export declare function fileMove(filePath: string, newPath: string): void | boolean;
35
35
  export declare function filesMove(dirSource: string, dirTarget: string, dirSub: string, formatDir: Record<string, string>): string[];
36
- export declare function fileOpen(filePath: string): Buffer<ArrayBufferLike>;
36
+ export declare function fileOpen(filePath: string, options?: string[]): import("child_process").ChildProcess | Buffer<ArrayBufferLike>;
37
37
  export declare function fileRead(filePath: string): string;
38
38
  export declare function fileReadJson(filePath: string): any;
39
39
  export declare function fileReadString(filePath: string): string;
@@ -247,8 +247,9 @@ export function fileMove(filePath, newPath) {
247
247
  return false;
248
248
  }
249
249
  export function filesMove(dirSource, dirTarget, dirSub, formatDir) {
250
- // Read files from source directory, ignoring Mac Contents files.
251
- const files = dirRead(`${dirSource}/**/*.*`);
250
+ // Read all files from source directory, ignoring Mac Contents files.
251
+ const allFiles = dirRead(`${dirSource}/**/*`);
252
+ const files = allFiles.filter(f => !dirIs(f));
252
253
  const filesMoved = [];
253
254
  // For each file, move to correct folder based on type
254
255
  files.forEach((fileSource) => {
@@ -256,7 +257,7 @@ export function filesMove(dirSource, dirTarget, dirSub, formatDir) {
256
257
  const fileExtTarget = formatDir[fileExt];
257
258
  // If this is not a supported file format, then ignore.
258
259
  if (fileExtTarget === undefined)
259
- return log(`${fileSource} - ${fileExt} not mapped to a installation folder, skipping.`);
260
+ return log(`${fileSource} - ${fileExt || 'no extension'} not mapped to a installation folder, skipping.`);
260
261
  const fileTarget = path.join(dirTarget, fileExtTarget, dirSub, path.basename(fileSource));
261
262
  if (fileExists(fileTarget))
262
263
  return log(`${fileSource} - ${fileTarget} already exists, skipping.`);
@@ -270,21 +271,32 @@ export function filesMove(dirSource, dirTarget, dirSub, formatDir) {
270
271
  fileExec(executablePath);
271
272
  }
272
273
  }
273
- else if (['elf', 'exe'].includes(fileExt)) {
274
+ else if (['elf', 'exe', ''].includes(fileExt)) {
274
275
  fileExec(fileTarget);
275
276
  }
276
277
  filesMoved.push(fileTarget);
277
278
  });
278
279
  return filesMoved;
279
280
  }
280
- export function fileOpen(filePath) {
281
- let command = '';
281
+ export function fileOpen(filePath, options = []) {
282
282
  if (process.env.CI)
283
283
  return Buffer.from('');
284
+ if (getSystem() === SystemType.Mac) {
285
+ const isExecutable = !path.extname(filePath);
286
+ if (isExecutable) {
287
+ // Use spawn for executables with stdio inherit to show output
288
+ log('⎋', `spawn "${filePath}" ${options.join(' ')}`);
289
+ const child = spawn(filePath, options, { stdio: 'inherit' });
290
+ return child;
291
+ }
292
+ else {
293
+ log('⎋', `open "${filePath}"`);
294
+ return execSync(`open "${filePath}"`);
295
+ }
296
+ }
297
+ let command = '';
284
298
  if (getSystem() === SystemType.Win)
285
299
  command = 'start ""';
286
- else if (getSystem() === SystemType.Mac)
287
- command = 'open';
288
300
  else
289
301
  command = 'xdg-open';
290
302
  log('⎋', `${command} "${filePath}"`);
@@ -19,7 +19,9 @@ export declare enum PluginFormat {
19
19
  export type PluginFormatDir = {
20
20
  [format in PluginFormat]: string;
21
21
  };
22
- export declare const pluginFormatDir: PluginFormatDir;
22
+ export declare const pluginFormatDir: PluginFormatDir & {
23
+ '': string;
24
+ };
23
25
  export interface PluginFormatOption {
24
26
  description: string;
25
27
  value: PluginFormat;
@@ -34,6 +34,7 @@ export const pluginFormatDir = {
34
34
  [PluginFormat.VSTMac]: 'VST',
35
35
  [PluginFormat.VSTWin]: 'VST',
36
36
  [PluginFormat.WinStandalone]: 'Exe',
37
+ '': 'App',
37
38
  };
38
39
  export const pluginFormats = [
39
40
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-audio-stack/core",
3
- "version": "0.1.42",
3
+ "version": "0.1.43",
4
4
  "description": "Open-source audio plugin management software",
5
5
  "type": "module",
6
6
  "main": "./build/index.js",