Skip to content

Commit c9f97b8

Browse files
authored
Merge pull request #22 from studiorack/feature/apps
Feature/apps
2 parents 05bf297 + 21cb08e commit c9f97b8

33 files changed

+566
-189
lines changed

package-lock.json

Lines changed: 32 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@studiorack/cli",
3-
"version": "3.0.5",
3+
"version": "3.0.6",
44
"description": "Audio project manager tool",
55
"type": "module",
66
"main": "./build/index.js",
@@ -39,7 +39,7 @@
3939
"node": ">=18"
4040
},
4141
"dependencies": {
42-
"@open-audio-stack/core": "^0.1.45",
42+
"@open-audio-stack/core": "^0.1.47",
4343
"cli-table3": "^0.6.5",
4444
"commander": "^12.1.0",
4545
"ora": "^9.0.0"

src/commands/config.ts

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Command } from 'commander';
22
import { CliOptions } from '../types/options.js';
33
import { ConfigInterface, ConfigLocal, isTests } from '@open-audio-stack/core';
44
import { CONFIG_LOCAL_TEST } from '../data/Config.js';
5+
import { output, OutputType } from '../utils.js';
56

67
const config: ConfigLocal = new ConfigLocal(isTests() ? CONFIG_LOCAL_TEST : undefined);
78
const program = new Command();
@@ -13,13 +14,16 @@ configCmd
1314
.option('-l, --log', 'Enable logging')
1415
.description('Get a config setting by key')
1516
.action((key: keyof ConfigInterface, options: CliOptions) => {
16-
if (options.log) config.logEnable();
17-
if (options.json) {
18-
const obj: any = {};
19-
obj[key] = config.get(key);
20-
console.log({ key });
21-
} else {
22-
console.log(config.get(key));
17+
{
18+
const message = `Get config ${String(key)}`;
19+
output(OutputType.START, message, options, config);
20+
try {
21+
const payload = options && options.json ? { key, value: config.get(key) } : String(config.get(key));
22+
output(OutputType.SUCCESS, payload, options, config);
23+
} catch (err: any) {
24+
output(OutputType.ERROR, err, options, config);
25+
process.exit(1);
26+
}
2327
}
2428
});
2529

@@ -29,12 +33,16 @@ configCmd
2933
.option('-l, --log', 'Enable logging')
3034
.description('Set a config setting by key and value')
3135
.action((key: keyof ConfigInterface, val: any, options: CliOptions) => {
32-
// if (options.log) config.logEnable();
33-
if (options.json) {
34-
const obj: any = {};
35-
obj[key] = config.set(key, val);
36-
console.log(obj);
37-
} else {
38-
console.log(config.set(key, val));
36+
{
37+
const message = `Set config ${String(key)}`;
38+
output(OutputType.START, message, options, config);
39+
try {
40+
const res = config.set(key, val);
41+
const payload = options && options.json ? { key, value: res } : String(res);
42+
output(OutputType.SUCCESS, payload, options, config);
43+
} catch (err: any) {
44+
output(OutputType.ERROR, err, options, config);
45+
process.exit(1);
46+
}
3947
}
4048
});

src/commands/create.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,26 @@
11
import { Command } from 'commander';
22
import { CliOptions } from '../types/options.js';
33
import { ManagerLocal } from '@open-audio-stack/core';
4+
import { output, OutputType } from '../utils.js';
45

56
export function create(command: Command, manager: ManagerLocal) {
67
command
7-
.command('create <path>')
8+
.command('create')
9+
.option('-j, --json', 'Output results as json')
810
.option('-l, --log', 'Enable logging')
911
.description('Create a new package locally')
10-
.action(async (path: string, options: CliOptions) => {
11-
if (options.log) manager.logEnable();
12-
else manager.logDisable();
13-
console.log(await manager.create());
14-
console.log(path);
12+
.action(async (options: CliOptions) => {
13+
const message = `Create package`;
14+
output(OutputType.START, message, options, manager);
15+
try {
16+
const result = await manager.create();
17+
// For JSON mode return the object; for textual mode, stringify objects
18+
const payload =
19+
options && options.json ? result : typeof result === 'string' ? result : JSON.stringify(result, null, 2);
20+
output(OutputType.SUCCESS, payload, options, manager);
21+
} catch (err: any) {
22+
output(OutputType.ERROR, err, options, manager);
23+
process.exit(1);
24+
}
1525
});
1626
}

src/commands/filter.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,35 @@
11
import { Command } from 'commander';
22
import { CliOptions } from '../types/options.js';
33
import { ManagerLocal, PackageVersion } from '@open-audio-stack/core';
4-
import { formatOutput } from '../utils.js';
4+
import { formatOutput, output, OutputType } from '../utils.js';
55

66
export function filter(command: Command, manager: ManagerLocal) {
77
command
88
.command('filter <field> <value>')
9+
.option('-j, --json', 'Output results as json')
910
.option('-l, --log', 'Enable logging')
1011
.description('Filter the by field and matching value')
11-
.action((field: keyof PackageVersion, value: string, options: CliOptions) => {
12-
if (options.log) manager.logEnable();
13-
else manager.logDisable();
14-
console.log(formatOutput(manager.filter(pkgVersion => pkgVersion[field] === value)));
12+
.action(async (field: keyof PackageVersion, value: string, options: CliOptions) => {
13+
const message = `Filter ${manager.type} by ${String(field)}=${value}`;
14+
output(OutputType.START, message, options, manager);
15+
try {
16+
const predicate = (pkgVersion: PackageVersion) => {
17+
const fieldVal: any = pkgVersion[field];
18+
if (Array.isArray(fieldVal)) {
19+
return fieldVal.some((v: any) => String(v).toLowerCase() === value.toLowerCase());
20+
}
21+
if (typeof fieldVal === 'string') {
22+
return fieldVal.toLowerCase().includes(value.toLowerCase());
23+
}
24+
if (fieldVal === undefined || fieldVal === null) return false;
25+
return String(fieldVal) === value;
26+
};
27+
const result = await manager.filter(predicate);
28+
const payload = options && options.json ? result : formatOutput(result);
29+
output(OutputType.SUCCESS, payload, options, manager);
30+
} catch (err: any) {
31+
output(OutputType.ERROR, err, options, manager);
32+
process.exit(1);
33+
}
1534
});
1635
}

src/commands/get.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,29 @@
11
import { Command } from 'commander';
22
import { CliOptions } from '../types/options.js';
33
import { inputGetParts, ManagerLocal } from '@open-audio-stack/core';
4-
import { formatOutput } from '../utils.js';
4+
import { formatOutput, output, OutputType } from '../utils.js';
55

66
export function get(command: Command, manager: ManagerLocal) {
77
command
88
.command('get <input>')
9+
.option('-j, --json', 'Output results as json')
910
.option('-l, --log', 'Enable logging')
1011
.description('Get package metadata from registry')
1112
.action((input: string, options: CliOptions) => {
12-
if (options.log) manager.logEnable();
13-
else manager.logDisable();
14-
const [slug, version] = inputGetParts(input);
15-
const pkg = manager.getPackage(slug);
16-
const versions = version ? [version] : Array.from(pkg?.versions.keys() || new Map().keys());
17-
console.log(formatOutput(pkg, versions));
13+
const message = `Get package ${input}`;
14+
output(OutputType.START, message, options, manager);
15+
try {
16+
const [slug, version] = inputGetParts(input);
17+
const pkg = manager.getPackage(slug);
18+
if (!pkg) throw new Error(`No package found with slug: ${slug}`);
19+
const payload =
20+
options && options.json
21+
? { pkg, version }
22+
: formatOutput(pkg, version ? [version] : Array.from(pkg.versions.keys()), false);
23+
output(OutputType.SUCCESS, payload, options, manager);
24+
} catch (err: any) {
25+
output(OutputType.ERROR, err, options, manager);
26+
process.exit(1);
27+
}
1828
});
1929
}

src/commands/install.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
11
import { Command } from 'commander';
2-
import ora from 'ora';
32
import { CliOptions } from '../types/options.js';
4-
import { inputGetParts, ManagerLocal, isTests } from '@open-audio-stack/core';
3+
import { inputGetParts, ManagerLocal } from '@open-audio-stack/core';
4+
import { output, OutputType } from '../utils.js';
55

66
export function install(command: Command, manager: ManagerLocal) {
77
command
88
.command('install <input>')
9+
.option('-j, --json', 'Output results as json')
910
.option('-l, --log', 'Enable logging')
1011
.description('Install a package locally by slug/version')
1112
.action(async (input: string, options: CliOptions) => {
12-
if (options.log) manager.logEnable();
13-
else manager.logDisable();
1413
const [slug, version] = inputGetParts(input);
15-
const spinner = ora(`Installing ${slug}${version ? `@${version}` : ''}...`).start();
14+
const message = `Install ${slug}${version ? `@${version}` : ''}`;
15+
output(OutputType.START, message, options, manager);
1616
try {
1717
await manager.install(slug, version);
18-
spinner.succeed(`Installed ${slug}${version ? `@${version}` : ''}`);
19-
if (isTests()) console.log(`Installed ${slug}${version ? `@${version}` : ''}`);
20-
} catch (error) {
21-
const errorMessage = error instanceof Error ? error.message : String(error);
22-
spinner.fail(errorMessage);
23-
if (isTests()) console.log(errorMessage);
18+
const payload =
19+
options && options.json
20+
? { slug, version: version || null, installed: true }
21+
: `Installed ${slug}${version ? `@${version}` : ''}`;
22+
output(OutputType.SUCCESS, payload, options, manager);
23+
} catch (err: any) {
24+
output(OutputType.ERROR, err, options, manager);
25+
process.exit(1);
2426
}
2527
});
2628
}

src/commands/list.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Command } from 'commander';
22
import { CliOptions } from '../types/options.js';
33
import { ManagerLocal } from '@open-audio-stack/core';
4-
import { formatOutput } from '../utils.js';
4+
import { formatOutput, output, OutputType } from '../utils.js';
55

66
interface ListOptions extends CliOptions {
77
incompatible: boolean;
@@ -13,11 +13,19 @@ export function list(command: Command, manager: ManagerLocal) {
1313
.command('list')
1414
.option('-c, --incompatible', 'List incompatible packages')
1515
.option('-i, --installed', 'Only list installed packages')
16+
.option('-j, --json', 'Output results as json')
1617
.option('-l, --log', 'Enable logging')
1718
.description('List packages')
1819
.action(async (options: ListOptions) => {
19-
if (options.log) manager.logEnable();
20-
else manager.logDisable();
21-
console.log(formatOutput(manager.listPackages(options.installed, options.incompatible)));
20+
const message = `List ${manager.type}`;
21+
output(OutputType.START, message, options, manager);
22+
try {
23+
const result = await manager.listPackages(options.installed, options.incompatible);
24+
const payload = options && options.json ? result : formatOutput(result);
25+
output(OutputType.SUCCESS, payload, options, manager);
26+
} catch (err: any) {
27+
output(OutputType.ERROR, err, options, manager);
28+
process.exit(1);
29+
}
2230
});
2331
}

src/commands/open.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
import { Command } from 'commander';
22
import { CliOptions } from '../types/options.js';
33
import { inputGetParts, ManagerLocal } from '@open-audio-stack/core';
4+
import { output, OutputType } from '../utils.js';
45

56
export function open(command: Command, manager: ManagerLocal) {
67
command
78
.command('open <input> [options...]')
89
.option('-l, --log', 'Enable logging')
910
.description('Open a package by slug/version')
1011
.action(async (input: string, options: string[], cliOptions: CliOptions) => {
11-
if (cliOptions.log) manager.logEnable();
12-
else manager.logDisable();
13-
const [slug, version] = inputGetParts(input);
12+
const message = `Open ${input}`;
13+
output(OutputType.START, message, cliOptions, manager);
1414
try {
15+
const [slug, version] = inputGetParts(input);
1516
await manager.open(slug, version, options);
16-
} catch (error: any) {
17-
const errorMessage = error instanceof Error ? error.message : String(error);
18-
console.error(errorMessage);
17+
output(OutputType.SUCCESS, `Opened ${input}`, cliOptions, manager);
18+
} catch (err: any) {
19+
output(OutputType.ERROR, err, cliOptions, manager);
1920
process.exit(1);
2021
}
2122
});

src/commands/reset.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
import { Command } from 'commander';
22
import { CliOptions } from '../types/options.js';
33
import { ManagerLocal } from '@open-audio-stack/core';
4+
import { output, OutputType } from '../utils.js';
45

56
export function reset(command: Command, manager: ManagerLocal) {
67
command
78
.command('reset')
89
.option('-l, --log', 'Enable logging')
910
.description('Reset the synced package cache')
1011
.action((options: CliOptions) => {
11-
if (options.log) manager.logEnable();
12-
else manager.logDisable();
13-
manager.reset();
14-
console.log(`${manager.type} cache has been reset`);
12+
const message = `Reset ${manager.type}`;
13+
output(OutputType.START, message, options, manager);
14+
try {
15+
manager.reset();
16+
const payload =
17+
options && options.json ? { type: manager.type, status: 'reset' } : `Reset complete ${manager.type}`;
18+
output(OutputType.SUCCESS, payload, options, manager);
19+
} catch (err: any) {
20+
output(OutputType.ERROR, err, options, manager);
21+
process.exit(1);
22+
}
1523
});
1624
}

0 commit comments

Comments
 (0)