wip monorepo

This commit is contained in:
EthanShoeDev
2025-12-22 15:37:29 -05:00
parent 27309e1261
commit ac51644bda
69 changed files with 290 additions and 426 deletions

View File

@@ -0,0 +1,21 @@
{
"name": "dsc-ts",
"version": "0.0.1",
"type": "module",
"private": true,
"packageManager": "bun@1.3.3",
"scripts": {
"typecheck": "tsc --noEmit",
"gen:dsc-types": "bun run scripts/gen-dsc-types.ts",
"gen:dsc-resources-types": "bun run scripts/gen-dsc-resources-types.ts"
},
"dependencies": {
"@effect/cli": "catalog:",
"@effect/platform": "catalog:",
"@effect/platform-bun": "catalog:",
"effect": "catalog:"
},
"devDependencies": {
"typescript": "catalog:"
}
}

View File

@@ -0,0 +1,388 @@
import { Command, FileSystem, Path } from '@effect/platform';
import { BunContext, BunRuntime } from '@effect/platform-bun';
import { Effect, Logger, LogLevel, Schema as S } from 'effect';
import { jsonSchemaToEffectSchema } from './lib/script-utils';
// Schema for DSC resource list output
const DscResourceSchema = S.Struct({
type: S.String,
kind: S.String,
version: S.String,
capabilities: S.Array(S.String),
path: S.String,
description: S.NullOr(S.String),
directory: S.String,
manifest: S.Struct({
$schema: S.String,
type: S.String,
version: S.String,
description: S.optional(S.NullOr(S.String)),
schema: S.optional(
S.NullOr(
S.Union(
S.Struct({
command: S.Struct({
executable: S.String,
args: S.NullOr(S.Array(S.String)),
}),
}),
S.Struct({
embedded: S.Unknown,
}),
),
),
),
}),
});
type DscResource = S.Schema.Type<typeof DscResourceSchema>;
/**
* Sanitize a resource type name to be a valid TypeScript identifier and filename
* e.g., "Microsoft.WinGet/Package" -> "MicrosoftWinGetPackage"
*/
const sanitizeTypeName = (resourceType: string): string => {
return resourceType
.replace(/[/\\]/g, '') // Remove slashes
.replace(/\./g, '') // Remove dots
.replace(/[^a-zA-Z0-9]/g, ''); // Remove any other invalid chars
};
/**
* Convert resource type to a safe filename
* e.g., "Microsoft.WinGet/Package" -> "microsoft-winget-package"
*/
const toSafeFilename = (resourceType: string): string => {
return resourceType
.replace(/[/\\]/g, '-') // Replace slashes with hyphens
.replace(/\./g, '-') // Replace dots with hyphens
.toLowerCase();
};
/**
* Get schema for a DSC resource - either from embedded schema or via `dsc resource schema`
*/
const getDscResourceSchema = (resource: DscResource) =>
Effect.gen(function* () {
const schema = resource.manifest.schema;
if (!schema) {
yield* Effect.logDebug(`No schema defined for ${resource.type}`);
return null;
}
// Check if it's an embedded schema
if ('embedded' in schema) {
yield* Effect.logDebug(`Using embedded schema for ${resource.type}`);
return JSON.stringify(schema.embedded);
}
// Otherwise, use dsc resource schema command (more reliable than running executable directly)
if ('command' in schema) {
yield* Effect.logDebug(`Getting schema via DSC CLI for ${resource.type}`);
const schemaString = yield* Command.make(
'dsc',
'resource',
'schema',
'--resource',
resource.type,
).pipe(Command.string);
return schemaString.trim();
}
return null;
});
/**
* Parse NDJSON output (newline-delimited JSON) from dsc resource list
*/
const parseNdjson = (output: string): Array<unknown> =>
output
.split('\n')
.map((line) => line.trim())
.filter((line) => line.length > 0)
.map((line) => {
try {
return JSON.parse(line);
} catch {
return null;
}
})
.filter((obj): obj is unknown => obj !== null);
/**
* Get available DSC resources from the system
*/
const getAvailableDscResources = () =>
Effect.gen(function* () {
yield* Effect.logDebug('Getting available DSC resources...');
const dscrResourcesListOutput = yield* Command.make(
'dsc',
'resource',
'list',
'-o',
'json',
).pipe(Command.string);
// Parse NDJSON output
const rawResources = parseNdjson(dscrResourcesListOutput);
yield* Effect.log(`Found ${rawResources.length} resources in DSC output`);
// Decode each resource with the schema
const resources: Array<DscResource> = [];
for (const raw of rawResources) {
const decoded = S.decodeUnknownOption(DscResourceSchema)(raw);
if (decoded._tag === 'Some') {
resources.push(decoded.value);
} else {
// Log which resource failed to parse for debugging
const maybeType =
typeof raw === 'object' && raw !== null && 'type' in raw
? (raw as { type: unknown }).type
: 'unknown';
yield* Effect.logDebug(`Failed to decode resource: ${maybeType}`);
}
}
yield* Effect.log(`Successfully decoded ${resources.length} resources`);
return resources;
});
/**
* Generate index file that re-exports all types
*/
const generateIndexFile = (
resourceTypes: Array<{ type: string; filename: string; typeName: string }>,
) => {
const lines = [
'// This file is auto-generated. Do not edit manually.',
'// Re-exports all DSC resource schema types',
'',
];
for (const { filename, typeName } of resourceTypes) {
lines.push(`export * as ${typeName} from './${filename}.gen';`);
}
lines.push('');
return lines.join('\n');
};
/**
* Generate a types list file for all DSC resource configurations
*/
const generateDscConfigTypes = (
resourceTypes: Array<{ type: string; filename: string; typeName: string }>,
) => {
const lines = [
'// This file is auto-generated. Do not edit manually.',
"import * as S from 'effect/Schema';",
'',
];
// Create a resource types literal
lines.push('/**');
lines.push(' * All available DSC resource types on this system');
lines.push(' */');
lines.push('export const DscResourceTypes = S.Literal(');
for (const { type } of resourceTypes) {
lines.push(` "${type}",`);
}
lines.push(');');
lines.push('');
lines.push(
'export type DscResourceType = S.Schema.Type<typeof DscResourceTypes>;',
);
lines.push('');
// Create a map of type to schema import
lines.push('/**');
lines.push(' * Map of resource type to generated file');
lines.push(' */');
lines.push('export const ResourceTypeToFile = {');
for (const { type, filename } of resourceTypes) {
lines.push(` "${type}": "${filename}.gen",`);
}
lines.push('} as const;');
lines.push('');
return lines.join('\n');
};
/**
* Generate a resource union file that provides strong typing for the configuration DSL
*/
const generateResourceUnion = (
resourceTypes: Array<{ type: string; filename: string; typeName: string }>,
) => {
const lines = [
'// This file is auto-generated. Do not edit manually.',
"import * as S from 'effect/Schema';",
"import * as Resources from './index';",
'',
'/**',
' * A discriminated union of all available DSC resources with their specific properties',
' */',
'export const ResourceUnion = S.Union(',
];
for (const { type, typeName } of resourceTypes) {
lines.push(' S.Struct({');
lines.push(` type: S.Literal("${type}"),`);
lines.push(' name: S.String,');
lines.push(' dependsOn: S.optional(S.Array(S.String)),');
lines.push(` properties: Resources.${typeName}.${typeName},`);
lines.push(
' metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),',
);
lines.push(' }),');
}
lines.push(');');
lines.push('');
lines.push(
'export type ResourceUnion = S.Schema.Type<typeof ResourceUnion>;',
);
lines.push('');
return lines.join('\n');
};
const genDscResourcesTypes = Effect.gen(function* () {
yield* Effect.log('Starting DSC resources types generation...');
const resources = yield* getAvailableDscResources();
// Filter to only resources that have schemas and are not adapters
// (adapters like PowerShell adapter don't have their own config schema)
const resourcesWithSchemas = resources.filter(
(r) => r.manifest.schema && r.kind !== 'adapter',
);
yield* Effect.log(
`Found ${resourcesWithSchemas.length} resources with schemas (excluding adapters)`,
);
const fs = yield* FileSystem.FileSystem;
const path = yield* Path.Path;
const outputDir = path.join(
process.cwd(),
'src',
'dsc-resource-schema-types',
);
yield* Effect.logDebug(`Output directory: ${outputDir}`);
if (yield* fs.exists(outputDir)) {
yield* Effect.log('Removing existing output directory...');
yield* fs.remove(outputDir, { recursive: true, force: true });
}
yield* fs.makeDirectory(outputDir, { recursive: true });
const generatedTypes: Array<{
type: string;
filename: string;
typeName: string;
}> = [];
const errors: Array<{ type: string; error: string }> = [];
for (const resource of resourcesWithSchemas) {
yield* Effect.logDebug(`Processing: ${resource.type}`);
const schemaResult = yield* Effect.either(getDscResourceSchema(resource));
if (schemaResult._tag === 'Left') {
errors.push({
type: resource.type,
error: String(schemaResult.left),
});
yield* Effect.logWarning(
`Failed to get schema for ${resource.type}: ${schemaResult.left}`,
);
continue;
}
const jsonSchema = schemaResult.right;
if (!jsonSchema) {
yield* Effect.logDebug(`No schema available for ${resource.type}`);
continue;
}
const typeName = sanitizeTypeName(resource.type);
const filename = toSafeFilename(resource.type);
const effectSchemaResult = yield* Effect.either(
jsonSchemaToEffectSchema({
jsonSchema,
name: typeName,
}),
);
if (effectSchemaResult._tag === 'Left') {
errors.push({
type: resource.type,
error: String(effectSchemaResult.left),
});
yield* Effect.logWarning(
`Failed to convert schema for ${resource.type}: ${effectSchemaResult.left}`,
);
continue;
}
const effectSchema = effectSchemaResult.right;
const outputPath = path.join(outputDir, `${filename}.gen.ts`);
yield* fs.writeFileString(outputPath, effectSchema);
generatedTypes.push({
type: resource.type,
filename,
typeName,
});
yield* Effect.log(`Generated: ${filename}.gen.ts (${resource.type})`);
}
// Generate index file
if (generatedTypes.length > 0) {
const indexContent = generateIndexFile(generatedTypes);
const indexPath = path.join(outputDir, 'index.ts');
yield* fs.writeFileString(indexPath, indexContent);
yield* Effect.log('Generated: index.ts');
// Generate types list file
const typesListContent = generateDscConfigTypes(generatedTypes);
const typesListPath = path.join(outputDir, '_resource-types.gen.ts');
yield* fs.writeFileString(typesListPath, typesListContent);
yield* Effect.log('Generated: _resource-types.gen.ts');
// Generate resource union file
const unionContent = generateResourceUnion(generatedTypes);
const unionPath = path.join(outputDir, '_resource-union.gen.ts');
yield* fs.writeFileString(unionPath, unionContent);
yield* Effect.log('Generated: _resource-union.gen.ts');
}
yield* Effect.log('');
yield* Effect.log('=== Generation Summary ===');
yield* Effect.log(`Successfully generated: ${generatedTypes.length} types`);
if (errors.length > 0) {
yield* Effect.log(`Failed: ${errors.length} types`);
for (const { type, error } of errors) {
yield* Effect.logDebug(` - ${type}: ${error}`);
}
}
yield* Effect.log('DSC types generation complete!');
});
BunRuntime.runMain(
genDscResourcesTypes.pipe(
Effect.provide(BunContext.layer),
Logger.withMinimumLogLevel(LogLevel.Debug),
Effect.scoped,
),
);

View File

@@ -0,0 +1,82 @@
import { Command, FileSystem, Path } from '@effect/platform';
import { BunContext, BunRuntime } from '@effect/platform-bun';
import { Effect, Logger, LogLevel } from 'effect';
import { jsonSchemaToEffectSchema, runCommand } from './lib/script-utils';
const getDscJsonSchema = (schemaType: string) =>
Effect.gen(function* () {
const commandParts = ['dsc', 'schema', '--type', schemaType] as const;
yield* Effect.logDebug(`Running command: ${commandParts.join(' ')}`);
const schemaString = yield* Command.make(...commandParts).pipe(
Command.string,
);
return schemaString.trim();
});
const getPossibleDscSchemaTypes = () =>
Effect.gen(function* () {
yield* Effect.logDebug('Getting possible DSC schema types...');
const dscSchemaHelp = Command.make('dsc', 'schema', '--help');
const { stdout: dscHelpOutput } = yield* runCommand(dscSchemaHelp);
const possibleTypes = dscHelpOutput
.split('\n')
.filter((line) => line.includes('possible values:'))
.map((line) => {
const values = line.match(/\[possible values: (.+)\]/)?.[1];
return values?.split(', ') ?? [];
})[0];
if (!possibleTypes) return yield* Effect.die('No possible types found');
yield* Effect.logDebug(`Found ${possibleTypes.length} schema types`);
return possibleTypes;
});
const genDscTypes = Effect.gen(function* () {
yield* Effect.log('Starting DSC types generation...');
const possibleTypes = yield* getPossibleDscSchemaTypes();
yield* Effect.log(`Found schema types: ${possibleTypes.join(', ')}`);
const fs = yield* FileSystem.FileSystem;
const path = yield* Path.Path;
const outputDir = path.join(process.cwd(), 'src', 'dsc-schema-types');
yield* Effect.logDebug(`Output directory: ${outputDir}`);
if (yield* fs.exists(outputDir)) {
yield* Effect.log('Removing existing output directory...');
yield* fs.remove(outputDir, { recursive: true, force: true });
}
yield* fs.makeDirectory(outputDir, { recursive: true });
for (const schemaType of possibleTypes) {
yield* Effect.logDebug(`Processing: ${schemaType}`);
const jsonSchema = yield* getDscJsonSchema(schemaType);
const effectSchema = yield* jsonSchemaToEffectSchema({
jsonSchema,
name: schemaType,
});
const outputPath = path.join(outputDir, `${schemaType}.gen.ts`);
yield* fs.writeFileString(outputPath, effectSchema);
yield* Effect.log(`Generated: ${schemaType}.gen.ts`);
}
yield* Effect.log('DSC types generation complete!');
});
BunRuntime.runMain(
genDscTypes.pipe(
Effect.provide(BunContext.layer),
Logger.withMinimumLogLevel(LogLevel.Debug),
Effect.scoped,
),
);

View File

@@ -0,0 +1,684 @@
/**
* JSON Schema to Effect Schema Converter
*
* Converts JSON Schema to Effect Schema TypeScript code with proper
* handling of recursive types using S.suspend() and interface definitions.
*/
// ============================================================================
// Types
// ============================================================================
type JsonSchema = {
$ref?: string;
$defs?: Record<string, JsonSchema>;
definitions?: Record<string, JsonSchema>;
type?: string | Array<string>;
properties?: Record<string, JsonSchema>;
required?: Array<string>;
items?: JsonSchema;
enum?: Array<unknown>;
const?: unknown;
oneOf?: Array<JsonSchema>;
anyOf?: Array<JsonSchema>;
allOf?: Array<JsonSchema>;
additionalProperties?: boolean | JsonSchema;
title?: string;
description?: string;
default?: unknown;
nullable?: boolean;
};
type TypeDefinition = {
name: string;
schema: JsonSchema;
isRecursive: boolean;
dependencies: Set<string>;
};
type ConversionContext = {
definitions: Map<string, TypeDefinition>;
recursiveTypes: Set<string>;
currentPath: Array<string>;
};
// ============================================================================
// Utilities
// ============================================================================
/**
* Convert a string to PascalCase for type names
*/
function toPascalCase(str: string): string {
return str
.split(/[-_\s]+/)
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join('');
}
/**
* Extract the definition name from a $ref
*/
function getRefName(ref: string): string {
const parts = ref.split('/');
return parts.at(-1) ?? '';
}
/**
* Check if a schema represents null
*/
function isJsonSchemaNull(s: JsonSchema): boolean {
return (
typeof s === 'object' &&
s !== null &&
(s.type === 'null' || ('const' in s && s.const === null))
);
}
/**
* Check if a schema is nullable (has null in type array, nullable: true, or null in oneOf/anyOf)
*/
function isNullable(schema: JsonSchema): boolean {
if (typeof schema !== 'object' || schema === null) return false;
if (schema.nullable) return true;
if (Array.isArray(schema.type) && schema.type.includes('null')) return true;
// Check for null in oneOf/anyOf
const items = schema.oneOf || schema.anyOf;
if (items) {
return items.some(isJsonSchemaNull);
}
return false;
}
/**
* Get the non-null type from a schema
*/
function getNonNullType(schema: JsonSchema): string | undefined {
if (typeof schema !== 'object' || schema === null) return;
if (Array.isArray(schema.type)) {
const nonNull = schema.type.filter((t) => t !== 'null');
return nonNull.length === 1 ? nonNull[0] : undefined;
}
return schema.type;
}
// ============================================================================
// Schema Analysis
// ============================================================================
/**
* Collect all definitions from the schema
*/
function collectDefinitions(schema: JsonSchema): Map<string, TypeDefinition> {
const definitions = new Map<string, TypeDefinition>();
const defs = schema.$defs || schema.definitions || {};
for (const [name, defSchema] of Object.entries(defs)) {
definitions.set(name, {
name: toPascalCase(name),
schema: defSchema,
isRecursive: false,
dependencies: new Set(),
});
}
return definitions;
}
/**
* Find all $ref dependencies in a schema
*/
function findDependencies(schema: JsonSchema): Set<string> {
const deps = new Set<string>();
function traverse(s: JsonSchema): void {
if (typeof s !== 'object' || s === null) return;
if (s.$ref) {
deps.add(getRefName(s.$ref));
}
if (s.properties) {
for (const propSchema of Object.values(s.properties)) {
traverse(propSchema);
}
}
if (s.items) {
traverse(s.items);
}
if (s.oneOf) {
for (const item of s.oneOf) {
traverse(item);
}
}
if (s.anyOf) {
for (const item of s.anyOf) {
traverse(item);
}
}
if (s.allOf) {
for (const item of s.allOf) {
traverse(item);
}
}
if (typeof s.additionalProperties === 'object' && s.additionalProperties) {
traverse(s.additionalProperties);
}
}
traverse(schema);
return deps;
}
/**
* Detect recursive types using DFS cycle detection
*/
function detectRecursiveTypes(
definitions: Map<string, TypeDefinition>,
): Set<string> {
const recursiveTypes = new Set<string>();
// Build dependency graph
for (const [, def] of definitions) {
def.dependencies = findDependencies(def.schema);
}
// DFS to detect cycles
function hasCycle(
name: string,
visiting: Set<string>,
visited: Set<string>,
): boolean {
if (visiting.has(name)) {
return true;
}
if (visited.has(name)) {
return false;
}
visiting.add(name);
const def = definitions.get(name);
if (def) {
for (const dep of def.dependencies) {
if (hasCycle(dep, visiting, visited)) {
recursiveTypes.add(name);
recursiveTypes.add(dep);
}
}
}
visiting.delete(name);
visited.add(name);
return false;
}
// Check each definition for cycles
for (const name of definitions.keys()) {
hasCycle(name, new Set(), new Set());
}
// Also check for direct self-references
for (const [name, def] of definitions) {
if (def.dependencies.has(name)) {
recursiveTypes.add(name);
def.isRecursive = true;
}
}
// Mark all recursive types
for (const name of recursiveTypes) {
const def = definitions.get(name);
if (def) {
def.isRecursive = true;
}
}
return recursiveTypes;
}
/**
* Topologically sort definitions (dependencies first)
*/
function sortDefinitions(
definitions: Map<string, TypeDefinition>,
recursiveTypes: Set<string>,
): Array<TypeDefinition> {
const sorted: Array<TypeDefinition> = [];
const visited = new Set<string>();
function visit(name: string): void {
if (visited.has(name)) return;
visited.add(name);
const def = definitions.get(name);
if (!def) return;
// Visit non-recursive dependencies first
for (const dep of def.dependencies) {
if (!(recursiveTypes.has(dep) && recursiveTypes.has(name))) {
visit(dep);
}
}
sorted.push(def);
}
for (const name of definitions.keys()) {
visit(name);
}
return sorted;
}
// ============================================================================
// Code Generation
// ============================================================================
/**
* Generate TypeScript type for a JSON Schema (used for recursive type declarations)
*/
function generateTsType(schema: JsonSchema, _ctx: ConversionContext): string {
if (typeof schema === 'boolean') {
return schema ? 'any' : 'never';
}
if (schema.$ref) {
const refName = getRefName(schema.$ref);
const pascalName = toPascalCase(refName);
return pascalName;
}
const type = getNonNullType(schema);
if (schema.enum) {
return schema.enum.map((v) => JSON.stringify(v)).join(' | ');
}
if (schema.const !== undefined) {
return JSON.stringify(schema.const);
}
if (schema.oneOf || schema.anyOf) {
const items = schema.oneOf || schema.anyOf || [];
const types = items
.filter((s) => !isJsonSchemaNull(s))
.map((s) => generateTsType(s, _ctx));
return types.join(' | ');
}
switch (type) {
case 'string':
return 'string';
case 'number':
case 'integer':
return 'number';
case 'boolean':
return 'boolean';
case 'null':
return 'null';
case 'array':
if (schema.items) {
return `ReadonlyArray<${generateTsType(schema.items, _ctx)}>`;
}
return 'ReadonlyArray<unknown>';
case 'object':
if (schema.properties) {
const props = Object.entries(schema.properties)
.map(([key, propSchema]) => {
const isRequired = schema.required?.includes(key) ?? false;
const nullable = isNullable(propSchema);
const tsType = generateTsType(propSchema, _ctx);
const nullSuffix = nullable ? ' | null' : '';
const optionalMark = isRequired ? '' : '?';
return ` readonly "${key}"${optionalMark}: ${tsType}${nullSuffix}`;
})
.join(';\n');
return `{\n${props}\n}`;
}
if (
schema.additionalProperties === true ||
typeof schema.additionalProperties === 'object'
) {
const valueType =
typeof schema.additionalProperties === 'object'
? generateTsType(schema.additionalProperties, _ctx)
: 'unknown';
return `Record<string, ${valueType}>`;
}
return 'Record<string, unknown>';
default:
return 'unknown';
}
}
/**
* Generate TypeScript interface/type declaration for a recursive type
*/
function generateTypeDeclaration(
name: string,
schema: JsonSchema,
ctx: ConversionContext,
): string {
const tsType = generateTsType(schema, ctx);
if (tsType.startsWith('{')) {
return `interface ${name} ${tsType}`;
}
return `type ${name} = ${tsType}`;
}
/**
* Generate Effect Schema code for a JSON Schema
*/
function generateEffectSchema(
schema: JsonSchema,
ctx: ConversionContext,
): string {
if (typeof schema === 'boolean') {
return schema ? 'S.Unknown' : 'S.Never';
}
// Handle $ref
if (schema.$ref) {
const refName = getRefName(schema.$ref);
const pascalName = toPascalCase(refName);
// Check if this is a recursive reference - use S.suspend with explicit return type
if (ctx.recursiveTypes.has(refName)) {
return `S.suspend((): S.Schema<${pascalName}> => ${pascalName})`;
}
return pascalName;
}
// Handle nullable types
const nullable = isNullable(schema);
const type = getNonNullType(schema);
// Handle enum
if (schema.enum) {
const literals = schema.enum.map((v) => JSON.stringify(v)).join(', ');
const result = `S.Literal(${literals})`;
return nullable ? `S.NullOr(${result})` : result;
}
// Handle const
if (schema.const !== undefined) {
const result = `S.Literal(${JSON.stringify(schema.const)})`;
return nullable ? `S.NullOr(${result})` : result;
}
// Handle oneOf / anyOf (union)
if (schema.oneOf || schema.anyOf) {
const items = schema.oneOf || schema.anyOf || [];
const nonNullItems = items.filter((s) => !isJsonSchemaNull(s));
if (nonNullItems.length === 0) {
return 'S.Null';
}
if (nonNullItems.length === 1) {
const firstItem = nonNullItems[0];
if (!firstItem) return 'S.Unknown';
const innerSchema = generateEffectSchema(firstItem, ctx);
const hasNull = items.some(isJsonSchemaNull);
return hasNull ? `S.NullOr(${innerSchema})` : innerSchema;
}
const members = nonNullItems
.map((s) => generateEffectSchema(s, ctx))
.join(', ');
const hasNull = items.some(isJsonSchemaNull);
return hasNull ? `S.Union(${members}, S.Null)` : `S.Union(${members})`;
}
// Handle allOf (intersection - we merge properties)
if (schema.allOf) {
// For simplicity, merge all schemas' properties
const merged: JsonSchema = { type: 'object', properties: {}, required: [] };
for (const item of schema.allOf) {
if (item.properties) {
merged.properties = { ...merged.properties, ...item.properties };
}
if (item.required) {
merged.required = [...(merged.required || []), ...item.required];
}
}
return generateEffectSchema(merged, ctx);
}
// Handle by type
switch (type) {
case 'string': {
const result = 'S.String';
return nullable ? `S.NullOr(${result})` : result;
}
case 'number':
case 'integer': {
const result = 'S.Number';
return nullable ? `S.NullOr(${result})` : result;
}
case 'boolean': {
const result = 'S.Boolean';
return nullable ? `S.NullOr(${result})` : result;
}
case 'null':
return 'S.Null';
case 'array': {
const itemSchema = schema.items
? generateEffectSchema(schema.items, ctx)
: 'S.Unknown';
const result = `S.Array(${itemSchema})`;
return nullable ? `S.NullOr(${result})` : result;
}
case 'object': {
if (schema.properties) {
const props = Object.entries(schema.properties)
.map(([key, propSchema]) => {
const isRequired = schema.required?.includes(key) ?? false;
const propNullable = isNullable(propSchema);
let propCode = generateEffectSchema(propSchema, ctx);
// Wrap in optional if not required
if (!isRequired) {
if (propNullable && !propCode.startsWith('S.NullOr(')) {
propCode = `S.NullOr(${propCode})`;
}
propCode = `S.optional(${propCode})`;
}
return ` "${key}": ${propCode}`;
})
.join(',\n');
const result = `S.Struct({\n${props}\n})`;
return nullable ? `S.NullOr(${result})` : result;
}
if (
schema.additionalProperties === true ||
typeof schema.additionalProperties === 'object'
) {
const valueSchema =
typeof schema.additionalProperties === 'object'
? generateEffectSchema(schema.additionalProperties, ctx)
: 'S.Unknown';
const result = `S.Record({ key: S.String, value: ${valueSchema} })`;
return nullable ? `S.NullOr(${result})` : result;
}
// Empty object or any object
const result = 'S.Record({ key: S.String, value: S.Unknown })';
return nullable ? `S.NullOr(${result})` : result;
}
default:
// Unknown or any type
return nullable ? 'S.NullOr(S.Unknown)' : 'S.Unknown';
}
}
/**
* Generate non-recursive schema definition (schema + derived type)
*/
function generateNonRecursiveDefinition(
def: TypeDefinition,
ctx: ConversionContext,
): string {
const lines: Array<string> = [];
const { name, schema } = def;
// Add description as JSDoc comment
if (schema.description) {
lines.push(`/** ${schema.description} */`);
}
// Check if it's an enum type
if (schema.enum) {
const literals = schema.enum.map((v) => JSON.stringify(v)).join(',\n ');
lines.push(`export const ${name} = S.Literal(\n ${literals}\n);`);
lines.push(`export type ${name} = S.Schema.Type<typeof ${name}>;`);
return lines.join('\n');
}
// Generate the schema
const schemaCode = generateEffectSchema(schema, ctx);
lines.push(`export const ${name} = ${schemaCode};`);
lines.push(`export type ${name} = S.Schema.Type<typeof ${name}>;`);
return lines.join('\n');
}
/**
* Generate recursive schema definition (schema with type assertion to bypass structural checks)
*/
function generateRecursiveSchemaDefinition(
def: TypeDefinition,
ctx: ConversionContext,
): string {
const lines: Array<string> = [];
const { name, schema } = def;
// Add description as JSDoc comment
if (schema.description) {
lines.push(`/** ${schema.description} */`);
}
// Generate the schema with double type assertion to bypass structural checking
const schemaCode = generateEffectSchema(schema, ctx);
lines.push(
`export const ${name} = ${schemaCode} as unknown as S.Schema<${name}>;`,
);
return lines.join('\n');
}
// ============================================================================
// Main Conversion Function
// ============================================================================
export type ConvertOptions = {
/** The JSON Schema to convert */
schema: JsonSchema;
/** The name for the root type (if the schema has no $ref) */
rootName?: string;
};
export type ConvertResult = {
/** The generated TypeScript code */
code: string;
/** Names of all generated types */
typeNames: Array<string>;
/** Names of recursive types */
recursiveTypes: Array<string>;
};
/**
* Convert a JSON Schema to Effect Schema TypeScript code
*/
export function convert(options: ConvertOptions): ConvertResult {
const { schema, rootName = 'Root' } = options;
// Collect all definitions
const definitions = collectDefinitions(schema);
// If the root schema is not a $ref, add it as a definition
if (!schema.$ref && (schema.type === 'object' || schema.properties)) {
definitions.set(rootName, {
name: toPascalCase(rootName),
schema,
isRecursive: false,
dependencies: new Set(),
});
}
// Detect recursive types
const recursiveTypes = detectRecursiveTypes(definitions);
// Create conversion context
const ctx: ConversionContext = {
definitions,
recursiveTypes,
currentPath: [],
};
// Sort definitions topologically
const sorted = sortDefinitions(definitions, recursiveTypes);
// Split into non-recursive and recursive definitions
const nonRecursive = sorted.filter((d) => !recursiveTypes.has(d.name));
const recursive = sorted.filter((d) => recursiveTypes.has(d.name));
// Generate code
const lines: Array<string> = [
'// This file is auto-generated. Do not edit manually.',
"import * as S from 'effect/Schema';",
'',
];
// 1. Generate non-recursive definitions (schema + type)
for (const def of nonRecursive) {
lines.push(generateNonRecursiveDefinition(def, ctx));
lines.push('');
}
// 2. Generate type declarations for recursive types (before schemas)
if (recursive.length > 0) {
lines.push('// Recursive type declarations');
for (const def of recursive) {
lines.push(generateTypeDeclaration(def.name, def.schema, ctx));
}
lines.push('');
// 3. Generate schema definitions for recursive types
lines.push('// Recursive schema definitions');
for (const def of recursive) {
lines.push(generateRecursiveSchemaDefinition(def, ctx));
lines.push('');
}
}
// Handle root $ref
if (schema.$ref) {
const refName = toPascalCase(getRefName(schema.$ref));
const exportName = toPascalCase(rootName);
if (refName !== exportName) {
lines.push(`export { ${refName} as ${exportName} };`);
lines.push('');
}
}
return {
code: lines.join('\n'),
typeNames: sorted.map((d) => d.name),
recursiveTypes: Array.from(recursiveTypes).map(toPascalCase),
};
}
/**
* Convert a JSON Schema string to Effect Schema TypeScript code
*/
export function convertFromString(
jsonSchemaString: string,
rootName = 'Root',
): ConvertResult {
const schema = JSON.parse(jsonSchemaString) as JsonSchema;
return convert({ schema, rootName });
}

View File

@@ -0,0 +1,47 @@
import { Command } from '@effect/platform';
import { Effect, pipe, Stream, String } from 'effect';
import { convertFromString } from './json-schema-to-effect';
// Helper function to collect stream output as a string
const runString = <E, R>(
stream: Stream.Stream<Uint8Array, E, R>,
): Effect.Effect<string, E, R> =>
stream.pipe(Stream.decodeText(), Stream.runFold(String.empty, String.concat));
export const runCommand = (command: Command.Command) =>
pipe(
Command.start(command),
Effect.flatMap((process) =>
Effect.all(
[
process.exitCode,
runString(process.stdout),
runString(process.stderr),
],
{ concurrency: 3 },
),
),
Effect.map(([exitCode, stdout, stderr]) => ({ exitCode, stdout, stderr })),
);
export const jsonSchemaToEffectSchema = (params: {
jsonSchema: string;
name: string;
}) =>
Effect.gen(function* () {
yield* Effect.logDebug(`Converting schema: ${params.name}`);
const result = convertFromString(params.jsonSchema, params.name);
yield* Effect.logDebug(
`Converted "${params.name}" - types: ${result.typeNames.join(', ')}`,
);
if (result.recursiveTypes.length > 0) {
yield* Effect.logInfo(
`Recursive types in ${params.name}: ${result.recursiveTypes.join(', ')}`,
);
}
return result.code;
});

View File

@@ -0,0 +1,96 @@
import { Command, Options } 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 {
decodeAndPrettyLogSetResult,
decodeAndPrettyLogTestResult,
} from './dsc-utils';
import { CommandUtils } from './utils';
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 configPathOption = Options.file('configFile', { exists: 'yes' }).pipe(
Options.withDefault('winos-config.ts'),
);
const setCommand = Command.make(
'set',
{
configPathOption,
},
({ configPathOption }) =>
Effect.gen(function* () {
yield* Effect.log('Applying configuration changes...');
yield* runDscConfig('set').pipe(Effect.scoped);
}),
);
const testCommand = Command.make(
'test',
{
configPathOption,
},
({ configPathOption }) =>
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);

View File

@@ -0,0 +1,106 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
/**
* All available DSC resource types on this system
*/
export const DscResourceTypes = S.Literal(
'Microsoft.DSC.Debug/Echo',
'Microsoft.DSC.Transitional/RunCommandOnSet',
'Microsoft.PowerToys/AdvancedPasteSettings',
'Microsoft.PowerToys/AlwaysOnTopSettings',
'Microsoft.PowerToys/AppSettings',
'Microsoft.PowerToys/AwakeSettings',
'Microsoft.PowerToys/ColorPickerSettings',
'Microsoft.PowerToys/CropAndLockSettings',
'Microsoft.PowerToys/EnvironmentVariablesSettings',
'Microsoft.PowerToys/FancyZonesSettings',
'Microsoft.PowerToys/FileLocksmithSettings',
'Microsoft.PowerToys/FindMyMouseSettings',
'Microsoft.PowerToys/HostsSettings',
'Microsoft.PowerToys/ImageResizerSettings',
'Microsoft.PowerToys/KeyboardManagerSettings',
'Microsoft.PowerToys/MeasureToolSettings',
'Microsoft.PowerToys/MouseHighlighterSettings',
'Microsoft.PowerToys/MouseJumpSettings',
'Microsoft.PowerToys/MousePointerCrosshairsSettings',
'Microsoft.PowerToys/PeekSettings',
'Microsoft.PowerToys/PowerAccentSettings',
'Microsoft.PowerToys/PowerOCRSettings',
'Microsoft.PowerToys/PowerRenameSettings',
'Microsoft.PowerToys/RegistryPreviewSettings',
'Microsoft.PowerToys/ShortcutGuideSettings',
'Microsoft.PowerToys/WorkspacesSettings',
'Microsoft.PowerToys/ZoomItSettings',
'Microsoft.WinGet/AdminSettings',
'Microsoft.WinGet/Package',
'Microsoft.WinGet/Source',
'Microsoft.WinGet/UserSettingsFile',
'Microsoft.Windows/RebootPending',
'Microsoft.Windows/Registry',
'Microsoft/OSInfo',
);
export type DscResourceType = S.Schema.Type<typeof DscResourceTypes>;
/**
* Map of resource type to generated file
*/
export const ResourceTypeToFile = {
'Microsoft.DSC.Debug/Echo': 'microsoft-dsc-debug-echo.gen',
'Microsoft.DSC.Transitional/RunCommandOnSet':
'microsoft-dsc-transitional-runcommandonset.gen',
'Microsoft.PowerToys/AdvancedPasteSettings':
'microsoft-powertoys-advancedpastesettings.gen',
'Microsoft.PowerToys/AlwaysOnTopSettings':
'microsoft-powertoys-alwaysontopsettings.gen',
'Microsoft.PowerToys/AppSettings': 'microsoft-powertoys-appsettings.gen',
'Microsoft.PowerToys/AwakeSettings': 'microsoft-powertoys-awakesettings.gen',
'Microsoft.PowerToys/ColorPickerSettings':
'microsoft-powertoys-colorpickersettings.gen',
'Microsoft.PowerToys/CropAndLockSettings':
'microsoft-powertoys-cropandlocksettings.gen',
'Microsoft.PowerToys/EnvironmentVariablesSettings':
'microsoft-powertoys-environmentvariablessettings.gen',
'Microsoft.PowerToys/FancyZonesSettings':
'microsoft-powertoys-fancyzonessettings.gen',
'Microsoft.PowerToys/FileLocksmithSettings':
'microsoft-powertoys-filelocksmithsettings.gen',
'Microsoft.PowerToys/FindMyMouseSettings':
'microsoft-powertoys-findmymousesettings.gen',
'Microsoft.PowerToys/HostsSettings': 'microsoft-powertoys-hostssettings.gen',
'Microsoft.PowerToys/ImageResizerSettings':
'microsoft-powertoys-imageresizersettings.gen',
'Microsoft.PowerToys/KeyboardManagerSettings':
'microsoft-powertoys-keyboardmanagersettings.gen',
'Microsoft.PowerToys/MeasureToolSettings':
'microsoft-powertoys-measuretoolsettings.gen',
'Microsoft.PowerToys/MouseHighlighterSettings':
'microsoft-powertoys-mousehighlightersettings.gen',
'Microsoft.PowerToys/MouseJumpSettings':
'microsoft-powertoys-mousejumpsettings.gen',
'Microsoft.PowerToys/MousePointerCrosshairsSettings':
'microsoft-powertoys-mousepointercrosshairssettings.gen',
'Microsoft.PowerToys/PeekSettings': 'microsoft-powertoys-peeksettings.gen',
'Microsoft.PowerToys/PowerAccentSettings':
'microsoft-powertoys-poweraccentsettings.gen',
'Microsoft.PowerToys/PowerOCRSettings':
'microsoft-powertoys-powerocrsettings.gen',
'Microsoft.PowerToys/PowerRenameSettings':
'microsoft-powertoys-powerrenamesettings.gen',
'Microsoft.PowerToys/RegistryPreviewSettings':
'microsoft-powertoys-registrypreviewsettings.gen',
'Microsoft.PowerToys/ShortcutGuideSettings':
'microsoft-powertoys-shortcutguidesettings.gen',
'Microsoft.PowerToys/WorkspacesSettings':
'microsoft-powertoys-workspacessettings.gen',
'Microsoft.PowerToys/ZoomItSettings':
'microsoft-powertoys-zoomitsettings.gen',
'Microsoft.WinGet/AdminSettings': 'microsoft-winget-adminsettings.gen',
'Microsoft.WinGet/Package': 'microsoft-winget-package.gen',
'Microsoft.WinGet/Source': 'microsoft-winget-source.gen',
'Microsoft.WinGet/UserSettingsFile': 'microsoft-winget-usersettingsfile.gen',
'Microsoft.Windows/RebootPending': 'microsoft-windows-rebootpending.gen',
'Microsoft.Windows/Registry': 'microsoft-windows-registry.gen',
'Microsoft/OSInfo': 'microsoft-osinfo.gen',
} as const;

View File

@@ -0,0 +1,300 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
import * as Resources from './index';
/**
* A discriminated union of all available DSC resources with their specific properties
*/
export const ResourceUnion = S.Union(
S.Struct({
type: S.Literal('Microsoft.DSC.Debug/Echo'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties: Resources.MicrosoftDSCDebugEcho.MicrosoftDSCDebugEcho,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.DSC.Transitional/RunCommandOnSet'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftDSCTransitionalRunCommandOnSet
.MicrosoftDSCTransitionalRunCommandOnSet,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/AdvancedPasteSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysAdvancedPasteSettings
.MicrosoftPowerToysAdvancedPasteSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/AlwaysOnTopSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysAlwaysOnTopSettings
.MicrosoftPowerToysAlwaysOnTopSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/AppSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysAppSettings.MicrosoftPowerToysAppSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/AwakeSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysAwakeSettings.MicrosoftPowerToysAwakeSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/ColorPickerSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysColorPickerSettings
.MicrosoftPowerToysColorPickerSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/CropAndLockSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysCropAndLockSettings
.MicrosoftPowerToysCropAndLockSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/EnvironmentVariablesSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysEnvironmentVariablesSettings
.MicrosoftPowerToysEnvironmentVariablesSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/FancyZonesSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysFancyZonesSettings
.MicrosoftPowerToysFancyZonesSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/FileLocksmithSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysFileLocksmithSettings
.MicrosoftPowerToysFileLocksmithSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/FindMyMouseSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysFindMyMouseSettings
.MicrosoftPowerToysFindMyMouseSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/HostsSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysHostsSettings.MicrosoftPowerToysHostsSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/ImageResizerSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysImageResizerSettings
.MicrosoftPowerToysImageResizerSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/KeyboardManagerSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysKeyboardManagerSettings
.MicrosoftPowerToysKeyboardManagerSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/MeasureToolSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysMeasureToolSettings
.MicrosoftPowerToysMeasureToolSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/MouseHighlighterSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysMouseHighlighterSettings
.MicrosoftPowerToysMouseHighlighterSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/MouseJumpSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysMouseJumpSettings
.MicrosoftPowerToysMouseJumpSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/MousePointerCrosshairsSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysMousePointerCrosshairsSettings
.MicrosoftPowerToysMousePointerCrosshairsSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/PeekSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysPeekSettings.MicrosoftPowerToysPeekSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/PowerAccentSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysPowerAccentSettings
.MicrosoftPowerToysPowerAccentSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/PowerOCRSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysPowerOCRSettings
.MicrosoftPowerToysPowerOCRSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/PowerRenameSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysPowerRenameSettings
.MicrosoftPowerToysPowerRenameSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/RegistryPreviewSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysRegistryPreviewSettings
.MicrosoftPowerToysRegistryPreviewSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/ShortcutGuideSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysShortcutGuideSettings
.MicrosoftPowerToysShortcutGuideSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/WorkspacesSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysWorkspacesSettings
.MicrosoftPowerToysWorkspacesSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.PowerToys/ZoomItSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftPowerToysZoomItSettings
.MicrosoftPowerToysZoomItSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.WinGet/AdminSettings'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftWinGetAdminSettings.MicrosoftWinGetAdminSettings,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.WinGet/Package'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties: Resources.MicrosoftWinGetPackage.MicrosoftWinGetPackage,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.WinGet/Source'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties: Resources.MicrosoftWinGetSource.MicrosoftWinGetSource,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.WinGet/UserSettingsFile'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftWinGetUserSettingsFile.MicrosoftWinGetUserSettingsFile,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.Windows/RebootPending'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties:
Resources.MicrosoftWindowsRebootPending.MicrosoftWindowsRebootPending,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft.Windows/Registry'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties: Resources.MicrosoftWindowsRegistry.MicrosoftWindowsRegistry,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
S.Struct({
type: S.Literal('Microsoft/OSInfo'),
name: S.String,
dependsOn: S.optional(S.Array(S.String)),
properties: Resources.MicrosoftOSInfo.MicrosoftOSInfo,
metadata: S.optional(S.Record({ key: S.String, value: S.Unknown })),
}),
);
export type ResourceUnion = S.Schema.Type<typeof ResourceUnion>;

View File

@@ -0,0 +1,37 @@
// This file is auto-generated. Do not edit manually.
// Re-exports all DSC resource schema types
export * as MicrosoftDSCDebugEcho from './microsoft-dsc-debug-echo.gen';
export * as MicrosoftDSCTransitionalRunCommandOnSet from './microsoft-dsc-transitional-runcommandonset.gen';
export * as MicrosoftOSInfo from './microsoft-osinfo.gen';
export * as MicrosoftPowerToysAdvancedPasteSettings from './microsoft-powertoys-advancedpastesettings.gen';
export * as MicrosoftPowerToysAlwaysOnTopSettings from './microsoft-powertoys-alwaysontopsettings.gen';
export * as MicrosoftPowerToysAppSettings from './microsoft-powertoys-appsettings.gen';
export * as MicrosoftPowerToysAwakeSettings from './microsoft-powertoys-awakesettings.gen';
export * as MicrosoftPowerToysColorPickerSettings from './microsoft-powertoys-colorpickersettings.gen';
export * as MicrosoftPowerToysCropAndLockSettings from './microsoft-powertoys-cropandlocksettings.gen';
export * as MicrosoftPowerToysEnvironmentVariablesSettings from './microsoft-powertoys-environmentvariablessettings.gen';
export * as MicrosoftPowerToysFancyZonesSettings from './microsoft-powertoys-fancyzonessettings.gen';
export * as MicrosoftPowerToysFileLocksmithSettings from './microsoft-powertoys-filelocksmithsettings.gen';
export * as MicrosoftPowerToysFindMyMouseSettings from './microsoft-powertoys-findmymousesettings.gen';
export * as MicrosoftPowerToysHostsSettings from './microsoft-powertoys-hostssettings.gen';
export * as MicrosoftPowerToysImageResizerSettings from './microsoft-powertoys-imageresizersettings.gen';
export * as MicrosoftPowerToysKeyboardManagerSettings from './microsoft-powertoys-keyboardmanagersettings.gen';
export * as MicrosoftPowerToysMeasureToolSettings from './microsoft-powertoys-measuretoolsettings.gen';
export * as MicrosoftPowerToysMouseHighlighterSettings from './microsoft-powertoys-mousehighlightersettings.gen';
export * as MicrosoftPowerToysMouseJumpSettings from './microsoft-powertoys-mousejumpsettings.gen';
export * as MicrosoftPowerToysMousePointerCrosshairsSettings from './microsoft-powertoys-mousepointercrosshairssettings.gen';
export * as MicrosoftPowerToysPeekSettings from './microsoft-powertoys-peeksettings.gen';
export * as MicrosoftPowerToysPowerAccentSettings from './microsoft-powertoys-poweraccentsettings.gen';
export * as MicrosoftPowerToysPowerOCRSettings from './microsoft-powertoys-powerocrsettings.gen';
export * as MicrosoftPowerToysPowerRenameSettings from './microsoft-powertoys-powerrenamesettings.gen';
export * as MicrosoftPowerToysRegistryPreviewSettings from './microsoft-powertoys-registrypreviewsettings.gen';
export * as MicrosoftPowerToysShortcutGuideSettings from './microsoft-powertoys-shortcutguidesettings.gen';
export * as MicrosoftPowerToysWorkspacesSettings from './microsoft-powertoys-workspacessettings.gen';
export * as MicrosoftPowerToysZoomItSettings from './microsoft-powertoys-zoomitsettings.gen';
export * as MicrosoftWindowsRebootPending from './microsoft-windows-rebootpending.gen';
export * as MicrosoftWindowsRegistry from './microsoft-windows-registry.gen';
export * as MicrosoftWinGetAdminSettings from './microsoft-winget-adminsettings.gen';
export * as MicrosoftWinGetPackage from './microsoft-winget-package.gen';
export * as MicrosoftWinGetSource from './microsoft-winget-source.gen';
export * as MicrosoftWinGetUserSettingsFile from './microsoft-winget-usersettingsfile.gen';

View File

@@ -0,0 +1,18 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const Output = S.Union(
S.Array(S.Unknown),
S.Boolean,
S.Number,
S.Unknown,
S.Unknown,
S.String,
S.String,
);
export type Output = S.Schema.Type<typeof Output>;
export const MicrosoftDSCDebugEcho = S.Struct({
output: Output,
});
export type MicrosoftDSCDebugEcho = S.Schema.Type<typeof MicrosoftDSCDebugEcho>;

View File

@@ -0,0 +1,11 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftDSCTransitionalRunCommandOnSet = S.Struct({
arguments: S.optional(S.Array(S.Unknown)),
executable: S.String,
exitCode: S.optional(S.Number),
});
export type MicrosoftDSCTransitionalRunCommandOnSet = S.Schema.Type<
typeof MicrosoftDSCTransitionalRunCommandOnSet
>;

View File

@@ -0,0 +1,17 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
/** Returns information about the operating system.
https://learn.microsoft.com/powershell/dsc/reference/microsoft/osinfo/resource
*/
export const MicrosoftOSInfo = S.Struct({
$id: S.optional(S.String),
architecture: S.optional(S.String),
bitness: S.optional(S.Literal('32', '64', 'unknown')),
codename: S.optional(S.String),
edition: S.optional(S.String),
family: S.optional(S.Literal('Linux', 'macOS', 'Windows')),
version: S.optional(S.String),
});
export type MicrosoftOSInfo = S.Schema.Type<typeof MicrosoftOSInfo>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysAdvancedPasteSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysAdvancedPasteSettings = S.Schema.Type<
typeof MicrosoftPowerToysAdvancedPasteSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysAlwaysOnTopSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysAlwaysOnTopSettings = S.Schema.Type<
typeof MicrosoftPowerToysAlwaysOnTopSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysAppSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysAppSettings = S.Schema.Type<
typeof MicrosoftPowerToysAppSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysAwakeSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysAwakeSettings = S.Schema.Type<
typeof MicrosoftPowerToysAwakeSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysColorPickerSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysColorPickerSettings = S.Schema.Type<
typeof MicrosoftPowerToysColorPickerSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysCropAndLockSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysCropAndLockSettings = S.Schema.Type<
typeof MicrosoftPowerToysCropAndLockSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysEnvironmentVariablesSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysEnvironmentVariablesSettings = S.Schema.Type<
typeof MicrosoftPowerToysEnvironmentVariablesSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysFancyZonesSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysFancyZonesSettings = S.Schema.Type<
typeof MicrosoftPowerToysFancyZonesSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysFileLocksmithSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysFileLocksmithSettings = S.Schema.Type<
typeof MicrosoftPowerToysFileLocksmithSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysFindMyMouseSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysFindMyMouseSettings = S.Schema.Type<
typeof MicrosoftPowerToysFindMyMouseSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysHostsSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysHostsSettings = S.Schema.Type<
typeof MicrosoftPowerToysHostsSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysImageResizerSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysImageResizerSettings = S.Schema.Type<
typeof MicrosoftPowerToysImageResizerSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysKeyboardManagerSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysKeyboardManagerSettings = S.Schema.Type<
typeof MicrosoftPowerToysKeyboardManagerSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysMeasureToolSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysMeasureToolSettings = S.Schema.Type<
typeof MicrosoftPowerToysMeasureToolSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysMouseHighlighterSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysMouseHighlighterSettings = S.Schema.Type<
typeof MicrosoftPowerToysMouseHighlighterSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysMouseJumpSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysMouseJumpSettings = S.Schema.Type<
typeof MicrosoftPowerToysMouseJumpSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysMousePointerCrosshairsSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysMousePointerCrosshairsSettings = S.Schema.Type<
typeof MicrosoftPowerToysMousePointerCrosshairsSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysPeekSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysPeekSettings = S.Schema.Type<
typeof MicrosoftPowerToysPeekSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysPowerAccentSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysPowerAccentSettings = S.Schema.Type<
typeof MicrosoftPowerToysPowerAccentSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysPowerOCRSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysPowerOCRSettings = S.Schema.Type<
typeof MicrosoftPowerToysPowerOCRSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysPowerRenameSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysPowerRenameSettings = S.Schema.Type<
typeof MicrosoftPowerToysPowerRenameSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysRegistryPreviewSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysRegistryPreviewSettings = S.Schema.Type<
typeof MicrosoftPowerToysRegistryPreviewSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysShortcutGuideSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysShortcutGuideSettings = S.Schema.Type<
typeof MicrosoftPowerToysShortcutGuideSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysWorkspacesSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysWorkspacesSettings = S.Schema.Type<
typeof MicrosoftPowerToysWorkspacesSettings
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftPowerToysZoomItSettings = S.Struct({
_inDesiredState: S.optional(S.NullOr(S.Boolean)),
settings: S.Unknown,
});
export type MicrosoftPowerToysZoomItSettings = S.Schema.Type<
typeof MicrosoftPowerToysZoomItSettings
>;

View File

@@ -0,0 +1,11 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftWindowsRebootPending = S.NullOr(
S.Struct({
rebootPending: S.optional(S.Boolean),
}),
);
export type MicrosoftWindowsRebootPending = S.Schema.Type<
typeof MicrosoftWindowsRebootPending
>;

View File

@@ -0,0 +1,41 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const Metadata = S.Struct({
whatIf: S.optional(S.NullOr(S.Array(S.String))),
});
export type Metadata = S.Schema.Type<typeof Metadata>;
export const RegistryValueData = S.Union(
S.Literal('None'),
S.Struct({
String: S.String,
}),
S.Struct({
ExpandString: S.String,
}),
S.Struct({
Binary: S.Array(S.Number),
}),
S.Struct({
DWord: S.Number,
}),
S.Struct({
MultiString: S.Array(S.String),
}),
S.Struct({
QWord: S.Number,
}),
);
export type RegistryValueData = S.Schema.Type<typeof RegistryValueData>;
export const MicrosoftWindowsRegistry = S.Struct({
_exist: S.optional(S.NullOr(S.Boolean)),
_metadata: S.optional(S.NullOr(Metadata)),
keyPath: S.String,
valueData: S.optional(S.NullOr(RegistryValueData)),
valueName: S.optional(S.NullOr(S.String)),
});
export type MicrosoftWindowsRegistry = S.Schema.Type<
typeof MicrosoftWindowsRegistry
>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftWinGetAdminSettings = S.Struct({
_inDesiredState: S.optional(S.Boolean),
settings: S.optional(S.Unknown),
});
export type MicrosoftWinGetAdminSettings = S.Schema.Type<
typeof MicrosoftWinGetAdminSettings
>;

View File

@@ -0,0 +1,24 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftWinGetPackage = S.Struct({
_exist: S.optional(S.Boolean),
_inDesiredState: S.optional(S.Boolean),
acceptAgreements: S.optional(S.Boolean),
id: S.String,
installMode: S.optional(S.Literal('default', 'silent', 'interactive')),
matchOption: S.optional(
S.Literal(
'equals',
'equalsCaseInsensitive',
'startsWithCaseInsensitive',
'containsCaseInsensitive',
),
),
source: S.optional(S.String),
useLatest: S.optional(S.Boolean),
version: S.optional(S.String),
});
export type MicrosoftWinGetPackage = S.Schema.Type<
typeof MicrosoftWinGetPackage
>;

View File

@@ -0,0 +1,14 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftWinGetSource = S.Struct({
_exist: S.optional(S.Boolean),
_inDesiredState: S.optional(S.Boolean),
acceptAgreements: S.optional(S.Boolean),
argument: S.optional(S.String),
explicit: S.optional(S.Boolean),
name: S.String,
trustLevel: S.optional(S.Literal('undefined', 'none', 'trusted')),
type: S.optional(S.String),
});
export type MicrosoftWinGetSource = S.Schema.Type<typeof MicrosoftWinGetSource>;

View File

@@ -0,0 +1,11 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const MicrosoftWinGetUserSettingsFile = S.Struct({
_inDesiredState: S.optional(S.Boolean),
action: S.optional(S.Literal('Partial', 'Full')),
settings: S.Unknown,
});
export type MicrosoftWinGetUserSettingsFile = S.Schema.Type<
typeof MicrosoftWinGetUserSettingsFile
>;

View File

@@ -0,0 +1,81 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const Operation = S.Literal('get', 'set', 'test', 'export');
export type Operation = S.Schema.Type<typeof Operation>;
export const ExecutionKind = S.Literal('actual', 'whatIf');
export type ExecutionKind = S.Schema.Type<typeof ExecutionKind>;
export const SecurityContextKind = S.Literal(
'current',
'elevated',
'restricted',
);
export type SecurityContextKind = S.Schema.Type<typeof SecurityContextKind>;
export const MicrosoftDscMetadata = S.Struct({
version: S.optional(S.NullOr(S.String)),
operation: S.optional(S.NullOr(Operation)),
executionType: S.optional(S.NullOr(ExecutionKind)),
startDatetime: S.optional(S.NullOr(S.String)),
endDatetime: S.optional(S.NullOr(S.String)),
duration: S.optional(S.NullOr(S.String)),
securityContext: S.optional(S.NullOr(SecurityContextKind)),
});
export type MicrosoftDscMetadata = S.Schema.Type<typeof MicrosoftDscMetadata>;
export const Metadata = S.Struct({
'Microsoft.DSC': S.optional(S.NullOr(MicrosoftDscMetadata)),
});
export type Metadata = S.Schema.Type<typeof Metadata>;
export const ResourceGetResponse = S.Struct({
actualState: S.Unknown,
});
export type ResourceGetResponse = S.Schema.Type<typeof ResourceGetResponse>;
export const MessageLevel = S.Literal('error', 'warning', 'information');
export type MessageLevel = S.Schema.Type<typeof MessageLevel>;
export const ResourceMessage = S.Struct({
name: S.String,
type: S.String,
message: S.String,
level: MessageLevel,
});
export type ResourceMessage = S.Schema.Type<typeof ResourceMessage>;
export const ConfigurationGetResult = S.Struct({
metadata: S.optional(S.NullOr(Metadata)),
results: S.Array(
S.suspend((): S.Schema<ResourceGetResult> => ResourceGetResult),
),
messages: S.Array(ResourceMessage),
hadErrors: S.Boolean,
});
export type ConfigurationGetResult = S.Schema.Type<
typeof ConfigurationGetResult
>;
// Recursive type declarations
type ResourceGetResult = {
readonly metadata?: Metadata | null;
readonly name: string;
readonly type: string;
readonly result: GetResult;
};
type GetResult = ResourceGetResponse | ReadonlyArray<ResourceGetResult>;
// Recursive schema definitions
export const ResourceGetResult = S.Struct({
metadata: S.optional(S.NullOr(Metadata)),
name: S.String,
type: S.String,
result: S.suspend((): S.Schema<GetResult> => GetResult),
}) as unknown as S.Schema<ResourceGetResult>;
export const GetResult = S.Union(
ResourceGetResponse,
S.Array(S.suspend((): S.Schema<ResourceGetResult> => ResourceGetResult)),
) as unknown as S.Schema<GetResult>;

View File

@@ -0,0 +1,83 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const Operation = S.Literal('get', 'set', 'test', 'export');
export type Operation = S.Schema.Type<typeof Operation>;
export const ExecutionKind = S.Literal('actual', 'whatIf');
export type ExecutionKind = S.Schema.Type<typeof ExecutionKind>;
export const SecurityContextKind = S.Literal(
'current',
'elevated',
'restricted',
);
export type SecurityContextKind = S.Schema.Type<typeof SecurityContextKind>;
export const MicrosoftDscMetadata = S.Struct({
version: S.optional(S.NullOr(S.String)),
operation: S.optional(S.NullOr(Operation)),
executionType: S.optional(S.NullOr(ExecutionKind)),
startDatetime: S.optional(S.NullOr(S.String)),
endDatetime: S.optional(S.NullOr(S.String)),
duration: S.optional(S.NullOr(S.String)),
securityContext: S.optional(S.NullOr(SecurityContextKind)),
});
export type MicrosoftDscMetadata = S.Schema.Type<typeof MicrosoftDscMetadata>;
export const Metadata = S.Struct({
'Microsoft.DSC': S.optional(S.NullOr(MicrosoftDscMetadata)),
});
export type Metadata = S.Schema.Type<typeof Metadata>;
export const ResourceSetResponse = S.Struct({
beforeState: S.Unknown,
afterState: S.Unknown,
changedProperties: S.optional(S.NullOr(S.Array(S.String))),
});
export type ResourceSetResponse = S.Schema.Type<typeof ResourceSetResponse>;
export const MessageLevel = S.Literal('error', 'warning', 'information');
export type MessageLevel = S.Schema.Type<typeof MessageLevel>;
export const ResourceMessage = S.Struct({
name: S.String,
type: S.String,
message: S.String,
level: MessageLevel,
});
export type ResourceMessage = S.Schema.Type<typeof ResourceMessage>;
export const ConfigurationSetResult = S.Struct({
metadata: S.optional(S.NullOr(Metadata)),
results: S.Array(
S.suspend((): S.Schema<ResourceSetResult> => ResourceSetResult),
),
messages: S.Array(ResourceMessage),
hadErrors: S.Boolean,
});
export type ConfigurationSetResult = S.Schema.Type<
typeof ConfigurationSetResult
>;
// Recursive type declarations
type ResourceSetResult = {
readonly metadata?: Metadata | null;
readonly name: string;
readonly type: string;
readonly result: SetResult;
};
type SetResult = ResourceSetResponse | ReadonlyArray<ResourceSetResult>;
// Recursive schema definitions
export const ResourceSetResult = S.Struct({
metadata: S.optional(S.NullOr(Metadata)),
name: S.String,
type: S.String,
result: S.suspend((): S.Schema<SetResult> => SetResult),
}) as unknown as S.Schema<ResourceSetResult>;
export const SetResult = S.Union(
ResourceSetResponse,
S.Array(S.suspend((): S.Schema<ResourceSetResult> => ResourceSetResult)),
) as unknown as S.Schema<SetResult>;

View File

@@ -0,0 +1,84 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const Operation = S.Literal('get', 'set', 'test', 'export');
export type Operation = S.Schema.Type<typeof Operation>;
export const ExecutionKind = S.Literal('actual', 'whatIf');
export type ExecutionKind = S.Schema.Type<typeof ExecutionKind>;
export const SecurityContextKind = S.Literal(
'current',
'elevated',
'restricted',
);
export type SecurityContextKind = S.Schema.Type<typeof SecurityContextKind>;
export const MicrosoftDscMetadata = S.Struct({
version: S.optional(S.NullOr(S.String)),
operation: S.optional(S.NullOr(Operation)),
executionType: S.optional(S.NullOr(ExecutionKind)),
startDatetime: S.optional(S.NullOr(S.String)),
endDatetime: S.optional(S.NullOr(S.String)),
duration: S.optional(S.NullOr(S.String)),
securityContext: S.optional(S.NullOr(SecurityContextKind)),
});
export type MicrosoftDscMetadata = S.Schema.Type<typeof MicrosoftDscMetadata>;
export const Metadata = S.Struct({
'Microsoft.DSC': S.optional(S.NullOr(MicrosoftDscMetadata)),
});
export type Metadata = S.Schema.Type<typeof Metadata>;
export const ResourceTestResponse = S.Struct({
desiredState: S.Unknown,
actualState: S.Unknown,
inDesiredState: S.Boolean,
differingProperties: S.Array(S.String),
});
export type ResourceTestResponse = S.Schema.Type<typeof ResourceTestResponse>;
export const MessageLevel = S.Literal('error', 'warning', 'information');
export type MessageLevel = S.Schema.Type<typeof MessageLevel>;
export const ResourceMessage = S.Struct({
name: S.String,
type: S.String,
message: S.String,
level: MessageLevel,
});
export type ResourceMessage = S.Schema.Type<typeof ResourceMessage>;
export const ConfigurationTestResult = S.Struct({
metadata: S.optional(S.NullOr(Metadata)),
results: S.Array(
S.suspend((): S.Schema<ResourceTestResult> => ResourceTestResult),
),
messages: S.Array(ResourceMessage),
hadErrors: S.Boolean,
});
export type ConfigurationTestResult = S.Schema.Type<
typeof ConfigurationTestResult
>;
// Recursive type declarations
type ResourceTestResult = {
readonly metadata?: Metadata | null;
readonly name: string;
readonly type: string;
readonly result: TestResult;
};
type TestResult = ResourceTestResponse | ReadonlyArray<ResourceTestResult>;
// Recursive schema definitions
export const ResourceTestResult = S.Struct({
metadata: S.optional(S.NullOr(Metadata)),
name: S.String,
type: S.String,
result: S.suspend((): S.Schema<TestResult> => TestResult),
}) as unknown as S.Schema<ResourceTestResult>;
export const TestResult = S.Union(
ResourceTestResponse,
S.Array(S.suspend((): S.Schema<ResourceTestResult> => ResourceTestResult)),
) as unknown as S.Schema<TestResult>;

View File

@@ -0,0 +1,99 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const DataType = S.Literal(
'string',
'secureString',
'int',
'bool',
'object',
'secureObject',
'array',
);
export type DataType = S.Schema.Type<typeof DataType>;
export const Parameter = S.Struct({
type: DataType,
defaultValue: S.optional(S.Unknown),
allowedValues: S.optional(S.NullOr(S.Array(S.Unknown))),
minValue: S.optional(S.NullOr(S.Number)),
maxValue: S.optional(S.NullOr(S.Number)),
minLength: S.optional(S.NullOr(S.Number)),
maxLength: S.optional(S.NullOr(S.Number)),
description: S.optional(S.NullOr(S.String)),
metadata: S.optional(S.NullOr(S.Record({ key: S.String, value: S.Unknown }))),
});
export type Parameter = S.Schema.Type<typeof Parameter>;
export const Resource = S.Struct({
type: S.String,
name: S.String,
dependsOn: S.optional(S.NullOr(S.Array(S.String))),
properties: S.optional(
S.NullOr(S.Record({ key: S.String, value: S.Unknown })),
),
metadata: S.optional(S.NullOr(S.Record({ key: S.String, value: S.Unknown }))),
});
export type Resource = S.Schema.Type<typeof Resource>;
export const Operation = S.Literal('get', 'set', 'test', 'export');
export type Operation = S.Schema.Type<typeof Operation>;
export const ExecutionKind = S.Literal('actual', 'whatIf');
export type ExecutionKind = S.Schema.Type<typeof ExecutionKind>;
export const SecurityContextKind = S.Literal(
'current',
'elevated',
'restricted',
);
export type SecurityContextKind = S.Schema.Type<typeof SecurityContextKind>;
export const MicrosoftDscMetadata = S.Struct({
version: S.optional(S.NullOr(S.String)),
operation: S.optional(S.NullOr(Operation)),
executionType: S.optional(S.NullOr(ExecutionKind)),
startDatetime: S.optional(S.NullOr(S.String)),
endDatetime: S.optional(S.NullOr(S.String)),
duration: S.optional(S.NullOr(S.String)),
securityContext: S.optional(S.NullOr(SecurityContextKind)),
});
export type MicrosoftDscMetadata = S.Schema.Type<typeof MicrosoftDscMetadata>;
export const Metadata = S.Struct({
'Microsoft.DSC': S.optional(S.NullOr(MicrosoftDscMetadata)),
});
export type Metadata = S.Schema.Type<typeof Metadata>;
export const Configuration = S.Struct({
$schema: S.Literal(
'https://aka.ms/dsc/schemas/v3/bundled/config/document.json',
'https://aka.ms/dsc/schemas/v3.0/bundled/config/document.json',
'https://aka.ms/dsc/schemas/v3.0.0/bundled/config/document.json',
'https://aka.ms/dsc/schemas/v3/bundled/config/document.vscode.json',
'https://aka.ms/dsc/schemas/v3.0/bundled/config/document.vscode.json',
'https://aka.ms/dsc/schemas/v3.0.0/bundled/config/document.vscode.json',
'https://aka.ms/dsc/schemas/v3/config/document.json',
'https://aka.ms/dsc/schemas/v3.0/config/document.json',
'https://aka.ms/dsc/schemas/v3.0.0/config/document.json',
'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3/bundled/config/document.json',
'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3.0/bundled/config/document.json',
'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3.0.0/bundled/config/document.json',
'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3/bundled/config/document.vscode.json',
'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3.0/bundled/config/document.vscode.json',
'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3.0.0/bundled/config/document.vscode.json',
'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3/config/document.json',
'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3.0/config/document.json',
'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3.0.0/config/document.json',
),
contentVersion: S.optional(S.NullOr(S.String)),
parameters: S.optional(
S.NullOr(S.Record({ key: S.String, value: Parameter })),
),
variables: S.optional(
S.NullOr(S.Record({ key: S.String, value: S.Unknown })),
),
resources: S.Array(Resource),
metadata: S.optional(S.NullOr(Metadata)),
});
export type Configuration = S.Schema.Type<typeof Configuration>;

View File

@@ -0,0 +1,42 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const Kind = S.Literal(
'adapter',
'exporter',
'group',
'importer',
'resource',
);
export type Kind = S.Schema.Type<typeof Kind>;
export const Capability = S.Union(
S.Literal('get'),
S.Literal('set'),
S.Literal('setHandlesExist'),
S.Literal('whatIf'),
S.Literal('test'),
S.Literal('delete'),
S.Literal('export'),
S.Literal('resolve'),
);
export type Capability = S.Schema.Type<typeof Capability>;
export const ImplementedAs = S.NullOr(S.String);
export type ImplementedAs = S.Schema.Type<typeof ImplementedAs>;
export const DscResource = S.Struct({
type: S.String,
kind: S.Struct({}),
version: S.String,
capabilities: S.Array(Capability),
path: S.String,
description: S.optional(S.NullOr(S.String)),
directory: S.String,
implementedAs: S.Struct({}),
author: S.optional(S.NullOr(S.String)),
properties: S.Array(S.String),
requireAdapter: S.optional(S.NullOr(S.String)),
manifest: S.optional(S.Unknown),
});
export type DscResource = S.Schema.Type<typeof DscResource>;

View File

@@ -0,0 +1,58 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const ResourceGetResponse = S.Struct({
actualState: S.Unknown,
});
export type ResourceGetResponse = S.Schema.Type<typeof ResourceGetResponse>;
export const Operation = S.Literal('get', 'set', 'test', 'export');
export type Operation = S.Schema.Type<typeof Operation>;
export const ExecutionKind = S.Literal('actual', 'whatIf');
export type ExecutionKind = S.Schema.Type<typeof ExecutionKind>;
export const SecurityContextKind = S.Literal(
'current',
'elevated',
'restricted',
);
export type SecurityContextKind = S.Schema.Type<typeof SecurityContextKind>;
export const MicrosoftDscMetadata = S.Struct({
version: S.optional(S.NullOr(S.String)),
operation: S.optional(S.NullOr(Operation)),
executionType: S.optional(S.NullOr(ExecutionKind)),
startDatetime: S.optional(S.NullOr(S.String)),
endDatetime: S.optional(S.NullOr(S.String)),
duration: S.optional(S.NullOr(S.String)),
securityContext: S.optional(S.NullOr(SecurityContextKind)),
});
export type MicrosoftDscMetadata = S.Schema.Type<typeof MicrosoftDscMetadata>;
export const Metadata = S.Struct({
'Microsoft.DSC': S.optional(S.NullOr(MicrosoftDscMetadata)),
});
export type Metadata = S.Schema.Type<typeof Metadata>;
// Recursive type declarations
type ResourceGetResult = {
readonly metadata?: Metadata | null;
readonly name: string;
readonly type: string;
readonly result: GetResult;
};
type GetResult = ResourceGetResponse | ReadonlyArray<ResourceGetResult>;
// Recursive schema definitions
export const ResourceGetResult = S.Struct({
metadata: S.optional(S.NullOr(Metadata)),
name: S.String,
type: S.String,
result: S.suspend((): S.Schema<GetResult> => GetResult),
}) as unknown as S.Schema<ResourceGetResult>;
export const GetResult = S.Union(
ResourceGetResponse,
S.Array(S.suspend((): S.Schema<ResourceGetResult> => ResourceGetResult)),
) as unknown as S.Schema<GetResult>;

View File

@@ -0,0 +1,12 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const Include = S.Union(
S.Struct({
configurationFile: S.String,
}),
S.Struct({
configurationContent: S.String,
}),
);
export type Include = S.Schema.Type<typeof Include>;

View File

@@ -0,0 +1,10 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const ResolveResult = S.Struct({
configuration: S.Unknown,
parameters: S.optional(
S.NullOr(S.Record({ key: S.String, value: S.Unknown })),
),
});
export type ResolveResult = S.Schema.Type<typeof ResolveResult>;

View File

@@ -0,0 +1,153 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const Kind = S.Literal(
'adapter',
'exporter',
'group',
'importer',
'resource',
);
export type Kind = S.Schema.Type<typeof Kind>;
export const ArgKind = S.Union(
S.String,
S.Struct({
jsonInputArg: S.String,
mandatory: S.optional(S.NullOr(S.Boolean)),
}),
);
export type ArgKind = S.Schema.Type<typeof ArgKind>;
export const InputKind = S.Union(S.Literal('env'), S.Literal('stdin'));
export type InputKind = S.Schema.Type<typeof InputKind>;
export const GetMethod = S.Struct({
executable: S.String,
args: S.optional(S.NullOr(S.Array(ArgKind))),
input: S.optional(S.NullOr(InputKind)),
});
export type GetMethod = S.Schema.Type<typeof GetMethod>;
export const ReturnKind = S.Union(
S.Literal('state'),
S.Literal('stateAndDiff'),
);
export type ReturnKind = S.Schema.Type<typeof ReturnKind>;
export const SetMethod = S.Struct({
executable: S.String,
args: S.optional(S.NullOr(S.Array(ArgKind))),
input: S.optional(S.NullOr(InputKind)),
implementsPretest: S.optional(S.NullOr(S.Boolean)),
handlesExist: S.optional(S.NullOr(S.Boolean)),
return: S.optional(S.NullOr(ReturnKind)),
});
export type SetMethod = S.Schema.Type<typeof SetMethod>;
export const TestMethod = S.Struct({
executable: S.String,
args: S.optional(S.NullOr(S.Array(ArgKind))),
input: S.optional(S.NullOr(InputKind)),
return: S.optional(S.NullOr(ReturnKind)),
});
export type TestMethod = S.Schema.Type<typeof TestMethod>;
export const DeleteMethod = S.Struct({
executable: S.String,
args: S.optional(S.NullOr(S.Array(ArgKind))),
input: S.optional(S.NullOr(InputKind)),
});
export type DeleteMethod = S.Schema.Type<typeof DeleteMethod>;
export const ExportMethod = S.Struct({
executable: S.String,
args: S.optional(S.NullOr(S.Array(ArgKind))),
input: S.optional(S.NullOr(InputKind)),
});
export type ExportMethod = S.Schema.Type<typeof ExportMethod>;
export const ResolveMethod = S.Struct({
executable: S.String,
args: S.optional(S.NullOr(S.Array(ArgKind))),
input: S.optional(S.NullOr(InputKind)),
});
export type ResolveMethod = S.Schema.Type<typeof ResolveMethod>;
export const ValidateMethod = S.Struct({
executable: S.String,
args: S.optional(S.NullOr(S.Array(ArgKind))),
input: S.optional(S.NullOr(InputKind)),
});
export type ValidateMethod = S.Schema.Type<typeof ValidateMethod>;
export const ListMethod = S.Struct({
executable: S.String,
args: S.optional(S.NullOr(S.Array(S.String))),
});
export type ListMethod = S.Schema.Type<typeof ListMethod>;
export const ConfigKind = S.Union(S.Literal('full'), S.Literal('sequence'));
export type ConfigKind = S.Schema.Type<typeof ConfigKind>;
export const Adapter = S.Struct({
list: S.Struct({}),
config: S.Struct({}),
});
export type Adapter = S.Schema.Type<typeof Adapter>;
export const SchemaCommand = S.Struct({
executable: S.String,
args: S.optional(S.NullOr(S.Array(S.String))),
});
export type SchemaCommand = S.Schema.Type<typeof SchemaCommand>;
export const SchemaKind = S.Union(
S.Struct({
command: SchemaCommand,
}),
S.Struct({
embedded: S.Unknown,
}),
);
export type SchemaKind = S.Schema.Type<typeof SchemaKind>;
export const ResourceManifest = S.Struct({
$schema: S.Literal(
'https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json',
'https://aka.ms/dsc/schemas/v3.0/bundled/resource/manifest.json',
'https://aka.ms/dsc/schemas/v3.0.0/bundled/resource/manifest.json',
'https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.vscode.json',
'https://aka.ms/dsc/schemas/v3.0/bundled/resource/manifest.vscode.json',
'https://aka.ms/dsc/schemas/v3.0.0/bundled/resource/manifest.vscode.json',
'https://aka.ms/dsc/schemas/v3/resource/manifest.json',
'https://aka.ms/dsc/schemas/v3.0/resource/manifest.json',
'https://aka.ms/dsc/schemas/v3.0.0/resource/manifest.json',
'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3/bundled/resource/manifest.json',
'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3.0/bundled/resource/manifest.json',
'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3.0.0/bundled/resource/manifest.json',
'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3/bundled/resource/manifest.vscode.json',
'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3.0/bundled/resource/manifest.vscode.json',
'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3.0.0/bundled/resource/manifest.vscode.json',
'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3/resource/manifest.json',
'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3.0/resource/manifest.json',
'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/v3.0.0/resource/manifest.json',
),
type: S.String,
kind: S.optional(S.NullOr(Kind)),
version: S.String,
description: S.optional(S.NullOr(S.String)),
tags: S.optional(S.NullOr(S.Array(S.String))),
get: S.optional(S.NullOr(GetMethod)),
set: S.optional(S.NullOr(SetMethod)),
whatIf: S.optional(S.NullOr(SetMethod)),
test: S.optional(S.NullOr(TestMethod)),
delete: S.optional(S.NullOr(DeleteMethod)),
export: S.optional(S.NullOr(ExportMethod)),
resolve: S.optional(S.NullOr(ResolveMethod)),
validate: S.optional(S.NullOr(ValidateMethod)),
adapter: S.optional(S.NullOr(Adapter)),
exitCodes: S.optional(S.NullOr(S.Record({ key: S.String, value: S.String }))),
schema: S.optional(S.NullOr(SchemaKind)),
});
export type ResourceManifest = S.Schema.Type<typeof ResourceManifest>;

View File

@@ -0,0 +1,60 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const ResourceSetResponse = S.Struct({
beforeState: S.Unknown,
afterState: S.Unknown,
changedProperties: S.optional(S.NullOr(S.Array(S.String))),
});
export type ResourceSetResponse = S.Schema.Type<typeof ResourceSetResponse>;
export const Operation = S.Literal('get', 'set', 'test', 'export');
export type Operation = S.Schema.Type<typeof Operation>;
export const ExecutionKind = S.Literal('actual', 'whatIf');
export type ExecutionKind = S.Schema.Type<typeof ExecutionKind>;
export const SecurityContextKind = S.Literal(
'current',
'elevated',
'restricted',
);
export type SecurityContextKind = S.Schema.Type<typeof SecurityContextKind>;
export const MicrosoftDscMetadata = S.Struct({
version: S.optional(S.NullOr(S.String)),
operation: S.optional(S.NullOr(Operation)),
executionType: S.optional(S.NullOr(ExecutionKind)),
startDatetime: S.optional(S.NullOr(S.String)),
endDatetime: S.optional(S.NullOr(S.String)),
duration: S.optional(S.NullOr(S.String)),
securityContext: S.optional(S.NullOr(SecurityContextKind)),
});
export type MicrosoftDscMetadata = S.Schema.Type<typeof MicrosoftDscMetadata>;
export const Metadata = S.Struct({
'Microsoft.DSC': S.optional(S.NullOr(MicrosoftDscMetadata)),
});
export type Metadata = S.Schema.Type<typeof Metadata>;
// Recursive type declarations
type ResourceSetResult = {
readonly metadata?: Metadata | null;
readonly name: string;
readonly type: string;
readonly result: SetResult;
};
type SetResult = ResourceSetResponse | ReadonlyArray<ResourceSetResult>;
// Recursive schema definitions
export const ResourceSetResult = S.Struct({
metadata: S.optional(S.NullOr(Metadata)),
name: S.String,
type: S.String,
result: S.suspend((): S.Schema<SetResult> => SetResult),
}) as unknown as S.Schema<ResourceSetResult>;
export const SetResult = S.Union(
ResourceSetResponse,
S.Array(S.suspend((): S.Schema<ResourceSetResult> => ResourceSetResult)),
) as unknown as S.Schema<SetResult>;

View File

@@ -0,0 +1,61 @@
// This file is auto-generated. Do not edit manually.
import * as S from 'effect/Schema';
export const ResourceTestResponse = S.Struct({
desiredState: S.Unknown,
actualState: S.Unknown,
inDesiredState: S.Boolean,
differingProperties: S.Array(S.String),
});
export type ResourceTestResponse = S.Schema.Type<typeof ResourceTestResponse>;
export const Operation = S.Literal('get', 'set', 'test', 'export');
export type Operation = S.Schema.Type<typeof Operation>;
export const ExecutionKind = S.Literal('actual', 'whatIf');
export type ExecutionKind = S.Schema.Type<typeof ExecutionKind>;
export const SecurityContextKind = S.Literal(
'current',
'elevated',
'restricted',
);
export type SecurityContextKind = S.Schema.Type<typeof SecurityContextKind>;
export const MicrosoftDscMetadata = S.Struct({
version: S.optional(S.NullOr(S.String)),
operation: S.optional(S.NullOr(Operation)),
executionType: S.optional(S.NullOr(ExecutionKind)),
startDatetime: S.optional(S.NullOr(S.String)),
endDatetime: S.optional(S.NullOr(S.String)),
duration: S.optional(S.NullOr(S.String)),
securityContext: S.optional(S.NullOr(SecurityContextKind)),
});
export type MicrosoftDscMetadata = S.Schema.Type<typeof MicrosoftDscMetadata>;
export const Metadata = S.Struct({
'Microsoft.DSC': S.optional(S.NullOr(MicrosoftDscMetadata)),
});
export type Metadata = S.Schema.Type<typeof Metadata>;
// Recursive type declarations
type ResourceTestResult = {
readonly metadata?: Metadata | null;
readonly name: string;
readonly type: string;
readonly result: TestResult;
};
type TestResult = ResourceTestResponse | ReadonlyArray<ResourceTestResult>;
// Recursive schema definitions
export const ResourceTestResult = S.Struct({
metadata: S.optional(S.NullOr(Metadata)),
name: S.String,
type: S.String,
result: S.suspend((): S.Schema<TestResult> => TestResult),
}) as unknown as S.Schema<ResourceTestResult>;
export const TestResult = S.Union(
ResourceTestResponse,
S.Array(S.suspend((): S.Schema<ResourceTestResult> => ResourceTestResult)),
) as unknown as S.Schema<TestResult>;

View File

@@ -0,0 +1,121 @@
import { Console, Effect, Schema as S } from 'effect';
import type { ResourceSetResponse } from './dsc-schema-types/configuration-set-result.gen';
import { ConfigurationSetResult as ConfigurationSetResultSchema } from './dsc-schema-types/configuration-set-result.gen';
import type { ResourceTestResponse } from './dsc-schema-types/configuration-test-result.gen';
import { ConfigurationTestResult as ConfigurationTestResultSchema } from './dsc-schema-types/configuration-test-result.gen';
/**
* Decodes and pretty-logs the result of a DSC configuration test operation.
*/
export const decodeAndPrettyLogTestResult = (stdout: string) =>
Effect.gen(function* () {
const raw = JSON.parse(stdout);
const result = yield* S.decodeUnknown(ConfigurationTestResultSchema)(raw);
const allInDesiredState = result.results.every((res) =>
'inDesiredState' in res.result
? (res.result as ResourceTestResponse).inDesiredState
: true,
);
yield* Console.log('\n--- DSC Test Result Summary ---');
if (result.hadErrors) {
yield* Console.error('🔴 Execution errors occurred during testing.');
}
if (allInDesiredState) {
yield* Console.log('✅ All resources are in the desired state.');
} else {
yield* Console.log('⚠️ Some resources are NOT in the desired state.');
}
for (const res of result.results) {
if ('inDesiredState' in res.result) {
const testResponse = res.result as ResourceTestResponse;
const status = testResponse.inDesiredState ? '✅' : '❌';
yield* Console.log(`${status} [${res.type}] ${res.name}`);
if (
!testResponse.inDesiredState &&
testResponse.differingProperties.length > 0
) {
yield* Console.log(
` Differing properties: ${testResponse.differingProperties.join(', ')}`,
);
for (const prop of testResponse.differingProperties) {
const desired = (
testResponse.desiredState as Record<string, unknown>
)?.[prop];
const actual = (
testResponse.actualState as Record<string, unknown>
)?.[prop];
yield* Console.log(` - ${prop}:`);
yield* Console.log(` Desired: ${JSON.stringify(desired)}`);
yield* Console.log(` Actual: ${JSON.stringify(actual)}`);
}
}
} else {
yield* Console.log(`📦 [Group: ${res.type}] ${res.name}`);
}
}
if (result.messages.length > 0) {
yield* Console.log('\nMessages:');
for (const msg of result.messages) {
const icon =
msg.level === 'error' ? '🔴' : msg.level === 'warning' ? '🟠' : '🔵';
yield* Console.log(`${icon} [${msg.type}] ${msg.message}`);
}
}
yield* Console.log('-------------------------------\n');
});
/**
* Decodes and pretty-logs the result of a DSC configuration set operation.
*/
export const decodeAndPrettyLogSetResult = (stdout: string) =>
Effect.gen(function* () {
const raw = JSON.parse(stdout);
const result = yield* S.decodeUnknown(ConfigurationSetResultSchema)(raw);
yield* Console.log('\n--- DSC Set Result Summary ---');
if (result.hadErrors) {
yield* Console.error('❌ Configuration set completed with errors.');
} else {
yield* Console.log('✅ Configuration set completed successfully.');
}
for (const res of result.results) {
if ('afterState' in res.result) {
const setResponse = res.result as ResourceSetResponse;
const changed =
setResponse.changedProperties &&
setResponse.changedProperties.length > 0;
const status = changed ? '🔄' : '✅';
yield* Console.log(`${status} [${res.type}] ${res.name}`);
if (changed) {
yield* Console.log(
` Changed properties: ${setResponse.changedProperties?.join(', ')}`,
);
}
} else {
yield* Console.log(`📦 [Group: ${res.type}] ${res.name}`);
}
}
if (result.messages.length > 0) {
yield* Console.log('\nMessages:');
for (const msg of result.messages) {
const icon =
msg.level === 'error' ? '🔴' : msg.level === 'warning' ? '🟠' : '🔵';
yield* Console.log(`${icon} [${msg.type}] ${msg.message}`);
}
}
yield* Console.log('-------------------------------\n');
});

View File

@@ -0,0 +1,54 @@
import * as S from 'effect/Schema';
import { ResourceUnion } from './dsc-resource-schema-types/_resource-union.gen';
import type * as Resources from './dsc-resource-schema-types/index';
import { Configuration as DscConfiguration } from './dsc-schema-types/configuration.gen';
/**
* Enhanced configuration schema with strong typing for resources.
* This extends the base DSC Configuration schema but overrides the 'resources'
* field with our strongly-typed union of all resources available on this system.
*/
export const Configuration = S.Struct({
...DscConfiguration.fields,
resources: S.Array(ResourceUnion),
});
export type Configuration = S.Schema.Type<typeof Configuration>;
/**
* Helper to define a configuration with full type safety.
* This provides a nice developer experience when defining the system state.
*
* @example
* const myConfig = defineConfig({
* $schema: 'https://aka.ms/dsc/schemas/v3/config/document.json',
* resources: [
* {
* type: 'Microsoft.WinGet/Package',
* name: 'Install VSCode',
* properties: {
* id: 'Microsoft.VisualStudioCode',
* ensure: 'Present'
* }
* }
* ]
* });
*/
export const defineConfig = (config: Configuration): Configuration => config;
export const defineWingetPackage = ({
id,
name,
...rest
}: {
id: string;
name?: string;
} & Partial<Resources.MicrosoftWinGetPackage.MicrosoftWinGetPackage>): Configuration['resources'][number] => ({
name: name ?? id,
type: 'Microsoft.WinGet/Package',
properties: {
id,
_exist: true,
...rest,
},
});

View File

@@ -0,0 +1,59 @@
import { Command, Path } from '@effect/platform';
import { Effect, Option, pipe, Stream, String } from 'effect';
export const CommandUtils = {
withLog: <A, E, R>(
cmd: Command.Command,
runner: (cmd: Command.Command) => Effect.Effect<A, E, R>,
) =>
Effect.gen(function* () {
const flattenedCmd = Command.flatten(cmd);
const [firstCmd] = flattenedCmd;
yield* Effect.logDebug(
`Running: '${flattenedCmd
.map((c) => `${c.command} ${c.args.join(' ')}`)
.join(' | ')}' in ${Option.getOrElse(firstCmd.cwd, () => '.')}`,
);
return yield* runner(cmd);
}),
/**
* Command.workingDirectory does not set the PWD env var.
*/
withCwd: (cwd: string) =>
Effect.gen(function* () {
const path = yield* Path.Path;
const absoluteCwd = path.resolve(path.join(process.cwd(), cwd));
return (cmd: Command.Command) =>
cmd.pipe(
Command.workingDirectory(absoluteCwd),
Command.env({ PWD: absoluteCwd }),
);
}),
bufferStringStream: <E, R>(
stream: Stream.Stream<Uint8Array, E, R>,
): Effect.Effect<string, E, R> =>
stream.pipe(
Stream.decodeText(),
Stream.runFold(String.empty, String.concat),
),
runCommandBuffered: (command: Command.Command) =>
pipe(
Command.start(command),
Effect.flatMap((process) =>
Effect.all(
[
process.exitCode,
CommandUtils.bufferStringStream(process.stdout),
CommandUtils.bufferStringStream(process.stderr),
],
{ concurrency: 3 },
),
),
Effect.map(([exitCode, stdout, stderr]) => ({
exitCode,
stdout,
stderr,
})),
),
};

View File

@@ -0,0 +1,16 @@
{
"name": "example-config",
"version": "0.0.1",
"type": "module",
"private": true,
"packageManager": "bun@1.3.3",
"scripts": {
"typecheck": "tsc --noEmit"
},
"dependencies": {
"dsc-ts": "workspace:*"
},
"devDependencies": {
"typescript": "catalog:"
}
}

View File

@@ -0,0 +1,22 @@
import { defineConfig, defineWingetPackage } from 'dsc-ts';
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' }),
],
});
export default machineConfig;