@open-audio-stack/core 0.1.36 → 0.1.38

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.
@@ -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;
@@ -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 (pkgVersion.installed) {
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
- return this.getPackage(slug)?.getVersion(versionNum);
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);
@@ -321,7 +333,7 @@ export class ManagerLocal extends Manager {
321
333
  const pkgVersion = pkg?.getVersion(versionNum);
322
334
  if (!pkgVersion)
323
335
  return this.log(`Package ${slug} version ${versionNum} not found in registry`);
324
- if (!pkgVersion.installed)
336
+ if (!this.isPackageInstalled(slug, versionNum))
325
337
  return this.log(`Package ${slug} version ${versionNum} not installed`);
326
338
  // Elevate permissions if not running as admin.
327
339
  if (!isAdmin() && !isTests()) {
@@ -331,7 +343,14 @@ export class ManagerLocal extends Manager {
331
343
  if (this.debug)
332
344
  command += ` --log`;
333
345
  await runCliAsAdmin(command);
334
- return this.getPackage(slug)?.getVersion(versionNum);
346
+ const returnedPkg = this.getPackage(slug)?.getVersion(versionNum);
347
+ if (returnedPkg) {
348
+ if (this.isPackageInstalled(slug, versionNum))
349
+ returnedPkg.installed = true;
350
+ else
351
+ delete returnedPkg.installed;
352
+ return returnedPkg;
353
+ }
335
354
  }
336
355
  // Delete all directories for this package version.
337
356
  const versionDirs = dirRead(path.join(this.typeDir, '**', slug, versionNum));
@@ -1,5 +1,5 @@
1
1
  import * as semver from 'semver';
2
- import { packageErrors, packageRecommendations } from '../helpers/package.js';
2
+ import { packageErrors, packageIsVerified, packageRecommendations } from '../helpers/package.js';
3
3
  import { isValidSlug } from '../helpers/utils.js';
4
4
  import { Base } from './Base.js';
5
5
  export class Package extends Base {
@@ -29,6 +29,7 @@ export class Package extends Base {
29
29
  this.reports.set(num, report);
30
30
  if (errors.length > 0)
31
31
  return this.log(`Package ${version.name} version ${num} errors`, errors);
32
+ version.verified = packageIsVerified(this.slug, version);
32
33
  this.versions.set(num, version);
33
34
  this.version = this.latestVersion();
34
35
  }
@@ -51,5 +51,6 @@ export async function adminInit() {
51
51
  else if (args.operation === 'installAll') {
52
52
  await manager.installAll();
53
53
  }
54
+ console.log('ADMIN_COMPLETE');
54
55
  }
55
56
  adminInit();
@@ -14,7 +14,7 @@ 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;
@@ -29,10 +29,10 @@ export declare function fileDelete(filePath: string): boolean | void;
29
29
  export declare function fileExec(filePath: string): void;
30
30
  export declare function fileExists(filePath: string): boolean;
31
31
  export declare function fileHash(filePath: string, algorithm?: string): Promise<string>;
32
- export declare function fileInstall(filePath: string): Buffer;
32
+ export declare function fileInstall(filePath: string): Buffer<ArrayBufferLike>;
33
33
  export declare function fileMove(filePath: string, newPath: string): void | boolean;
34
34
  export declare function filesMove(dirSource: string, dirTarget: string, dirSub: string, formatDir: Record<string, string>): string[];
35
- export declare function fileOpen(filePath: string): Buffer;
35
+ export declare function fileOpen(filePath: string): Buffer<ArrayBufferLike>;
36
36
  export declare function fileRead(filePath: string): string;
37
37
  export declare function fileReadJson(filePath: string): any;
38
38
  export declare function fileReadString(filePath: string): string;
@@ -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
- return zip.extractAllTo(dirPath);
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({
@@ -326,22 +347,24 @@ export function runCliAsAdmin(args) {
326
347
  const logFile = path.join(dirPathClean, 'admin.log');
327
348
  writeFileSync(logFile, ''); // Clear previous logs
328
349
  log(`Running as admin: node "${script}" ${args}`);
329
- // Tail the log file in real-time
350
+ // Monitor log file for completion
351
+ let completed = false;
330
352
  const tail = spawn('tail', ['-f', logFile]);
331
- const grep = spawn('grep', ['.']);
332
- tail.stdout.pipe(grep.stdin);
333
- grep.stdout.on('data', data => {
334
- log(data.toString());
353
+ tail.stdout.on('data', data => {
354
+ const output = data.toString();
355
+ log(output);
356
+ if (output.includes('ADMIN_COMPLETE')) {
357
+ completed = true;
358
+ tail.kill();
359
+ resolve();
360
+ }
335
361
  });
336
362
  // Run the script with sudoPrompt
337
363
  sudoPrompt.exec(`node "${script}" ${args} >> "${logFile}" 2>&1`, { name: 'Open Audio Stack' }, error => {
338
- tail.kill();
339
- if (error) {
364
+ if (error && !completed) {
365
+ tail.kill();
340
366
  reject(error);
341
367
  }
342
- else {
343
- resolve();
344
- }
345
368
  });
346
369
  });
347
370
  }
@@ -220,3 +220,4 @@ export declare function packageRecommendations(pkgVersion: PackageVersion): Pack
220
220
  export declare function packageRecommendationsUrl(obj: PackageVersion | PluginFile | PresetFile | ProjectFile, recs: PackageValidationRec[], field: string, domain?: string): void;
221
221
  export declare function packageJsToYaml(pkgVersion: PackageVersion): string;
222
222
  export declare function packageYamlToJs(pkgYaml: string): PackageVersion;
223
+ export declare function packageIsVerified(slug: string, pkgVersion: PackageVersion): boolean;
@@ -200,3 +200,16 @@ export function packageJsToYaml(pkgVersion) {
200
200
  export function packageYamlToJs(pkgYaml) {
201
201
  return yaml.load(pkgYaml);
202
202
  }
203
+ export function packageIsVerified(slug, pkgVersion) {
204
+ const org = slug.split('/')[0];
205
+ let verified = true;
206
+ pkgVersion.files.forEach(file => {
207
+ const url = file.url.toLowerCase();
208
+ const root = url.startsWith('https://github.com/') ? 'https://github.com/' + org + '/' : `https://${org}.`;
209
+ if (!url.startsWith(root)) {
210
+ verified = false;
211
+ return;
212
+ }
213
+ });
214
+ return verified;
215
+ }
@@ -24,6 +24,7 @@ export interface PackageBase {
24
24
  name: string;
25
25
  tags: string[];
26
26
  url: string;
27
+ verified?: boolean;
27
28
  }
28
29
  export interface PackageVersionReport {
29
30
  errors?: ZodIssue[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-audio-stack/core",
3
- "version": "0.1.36",
3
+ "version": "0.1.38",
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.6.3",
53
- "typescript-eslint": "^8.9.0",
52
+ "typescript": "^5.9.3",
53
+ "typescript-eslint": "^8.48.0",
54
54
  "vitest": "^3.0.5"
55
55
  },
56
56
  "dependencies": {