wip monorepo
This commit is contained in:
21
packages/dsc-ts/package.json
Normal file
21
packages/dsc-ts/package.json
Normal 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:"
|
||||
}
|
||||
}
|
||||
388
packages/dsc-ts/scripts/gen-dsc-resources-types.ts
Normal file
388
packages/dsc-ts/scripts/gen-dsc-resources-types.ts
Normal 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,
|
||||
),
|
||||
);
|
||||
82
packages/dsc-ts/scripts/gen-dsc-types.ts
Normal file
82
packages/dsc-ts/scripts/gen-dsc-types.ts
Normal 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,
|
||||
),
|
||||
);
|
||||
684
packages/dsc-ts/scripts/lib/json-schema-to-effect.ts
Normal file
684
packages/dsc-ts/scripts/lib/json-schema-to-effect.ts
Normal 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 });
|
||||
}
|
||||
47
packages/dsc-ts/scripts/lib/script-utils.ts
Normal file
47
packages/dsc-ts/scripts/lib/script-utils.ts
Normal 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;
|
||||
});
|
||||
96
packages/dsc-ts/src/bin.ts
Normal file
96
packages/dsc-ts/src/bin.ts
Normal 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);
|
||||
@@ -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;
|
||||
@@ -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>;
|
||||
37
packages/dsc-ts/src/dsc-resource-schema-types/index.ts
Normal file
37
packages/dsc-ts/src/dsc-resource-schema-types/index.ts
Normal 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';
|
||||
@@ -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>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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>;
|
||||
@@ -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
|
||||
>;
|
||||
@@ -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>;
|
||||
@@ -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>;
|
||||
@@ -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>;
|
||||
99
packages/dsc-ts/src/dsc-schema-types/configuration.gen.ts
Normal file
99
packages/dsc-ts/src/dsc-schema-types/configuration.gen.ts
Normal 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>;
|
||||
42
packages/dsc-ts/src/dsc-schema-types/dsc-resource.gen.ts
Normal file
42
packages/dsc-ts/src/dsc-schema-types/dsc-resource.gen.ts
Normal 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>;
|
||||
58
packages/dsc-ts/src/dsc-schema-types/get-result.gen.ts
Normal file
58
packages/dsc-ts/src/dsc-schema-types/get-result.gen.ts
Normal 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>;
|
||||
12
packages/dsc-ts/src/dsc-schema-types/include.gen.ts
Normal file
12
packages/dsc-ts/src/dsc-schema-types/include.gen.ts
Normal 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>;
|
||||
10
packages/dsc-ts/src/dsc-schema-types/resolve-result.gen.ts
Normal file
10
packages/dsc-ts/src/dsc-schema-types/resolve-result.gen.ts
Normal 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>;
|
||||
153
packages/dsc-ts/src/dsc-schema-types/resource-manifest.gen.ts
Normal file
153
packages/dsc-ts/src/dsc-schema-types/resource-manifest.gen.ts
Normal 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>;
|
||||
60
packages/dsc-ts/src/dsc-schema-types/set-result.gen.ts
Normal file
60
packages/dsc-ts/src/dsc-schema-types/set-result.gen.ts
Normal 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>;
|
||||
61
packages/dsc-ts/src/dsc-schema-types/test-result.gen.ts
Normal file
61
packages/dsc-ts/src/dsc-schema-types/test-result.gen.ts
Normal 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>;
|
||||
121
packages/dsc-ts/src/dsc-utils.ts
Normal file
121
packages/dsc-ts/src/dsc-utils.ts
Normal 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');
|
||||
});
|
||||
54
packages/dsc-ts/src/dsl.ts
Normal file
54
packages/dsc-ts/src/dsl.ts
Normal 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,
|
||||
},
|
||||
});
|
||||
59
packages/dsc-ts/src/utils.ts
Normal file
59
packages/dsc-ts/src/utils.ts
Normal 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,
|
||||
})),
|
||||
),
|
||||
};
|
||||
16
packages/example-config/package.json
Normal file
16
packages/example-config/package.json
Normal 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:"
|
||||
}
|
||||
}
|
||||
22
packages/example-config/winos-config.ts
Normal file
22
packages/example-config/winos-config.ts
Normal 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;
|
||||
Reference in New Issue
Block a user