Files
winos-config/src/bin.ts
2025-12-19 20:02:03 -05:00

103 lines
2.9 KiB
TypeScript

import { Command } from '@effect/cli';
import { Command as PlatformCommand } from '@effect/platform';
import { BunContext, BunRuntime } from '@effect/platform-bun';
import { Effect } from 'effect';
import pkg from '../package.json' with { type: 'json' };
import { defineConfig, defineWingetPackage } from './dsl';
import { CommandUtils } from './utils';
import {
decodeAndPrettyLogTestResult,
decodeAndPrettyLogSetResult,
} from './dsc-utils';
const machineConfig = defineConfig({
$schema: 'https://aka.ms/dsc/schemas/v3/config/document.json',
resources: [
// {
// name: 'example-registry-key',
// type: 'Microsoft.Windows/Registry',
// properties: {
// keyPath: 'HKCU\\Software\\WinosConfig',
// valueName: 'Version',
// valueData: {
// String: pkg.version,
// },
// _exist: true,
// },
// },
defineWingetPackage({ id: 'BurntSushi.ripgrep.MSVC' }),
],
});
const runDscConfig = (
subcommand: 'set' | 'test',
options: { whatIf?: boolean } = {},
) =>
Effect.gen(function* () {
const args = ['config', subcommand, '--file', '-'];
if (options.whatIf) {
args.push('--what-if');
}
yield* Effect.logDebug(`Running dsc ${args.join(' ')}`);
const command = PlatformCommand.make('dsc', ...args).pipe(
PlatformCommand.feed(JSON.stringify(machineConfig)),
);
const { exitCode, stdout, stderr } =
yield* CommandUtils.runCommandBuffered(command);
if (stderr) {
yield* Effect.logError(stderr);
}
if (exitCode !== 0) {
yield* Effect.logError(`DSC exited with code ${exitCode}`);
}
if (stdout) {
if (subcommand === 'test') {
yield* decodeAndPrettyLogTestResult(stdout);
} else if (subcommand === 'set') {
yield* decodeAndPrettyLogSetResult(stdout);
} else {
try {
const parsed = JSON.parse(stdout);
yield* Effect.log(JSON.stringify(parsed, null, 2));
} catch {
yield* Effect.log(stdout);
}
}
} else if (exitCode === 0 && !stderr) {
yield* Effect.log('DSC completed successfully with no output.');
}
});
const setCommand = Command.make('set', {}, () =>
Effect.gen(function* () {
yield* Effect.log('Applying configuration changes...');
yield* runDscConfig('set').pipe(Effect.scoped);
}),
);
const testCommand = Command.make('test', {}, () =>
Effect.gen(function* () {
yield* Effect.log('Running configuration test...');
yield* runDscConfig('test').pipe(Effect.scoped);
}),
);
const cliName = 'winos-config';
const app = Command.make(cliName, {}).pipe(
Command.withDescription('NixOS-like tool for windows'),
Command.withSubcommands([setCommand, testCommand]),
);
const cli = Command.run(app, {
name: cliName,
version: pkg.version,
});
cli(process.argv).pipe(Effect.provide(BunContext.layer), BunRuntime.runMain);