resolve static method

Future<CubeSpec?> resolve({
  1. required ExecutionEnv env,
  2. String? path,
  3. String? name,
  4. String? homeDir,
})

Resolves a cube manifest.

  • path — explicit manifest file (highest precedence). A leading ~/ is expanded with homeDir when known.
  • name — looks up <env.cwd>/.fah/cubes/<name>.yaml, falling back to the built-in preset with that id (project file wins over the preset).
  • neither — returns null.

A missing/unreadable file throws ConfigException('cube: file not found: <path> …') with the preset ids appended; invalid yaml or a schema violation propagates as ConfigException from the parser.

Implementation

static Future<CubeSpec?> resolve({
  required ExecutionEnv env,
  String? path,
  String? name,
  String? homeDir,
}) async {
  final String filePath;
  if (path != null) {
    final expanded = _expandHome(path, homeDir);
    if (expanded == null) {
      throw ConfigException(
        'cube: cannot expand "~" without a home directory: $path',
      );
    }
    filePath = expanded;
  } else if (name != null) {
    filePath = '${env.cwd}/.fah/cubes/$name.yaml';
  } else {
    return null;
  }
  final read = await env.readTextFile(filePath);
  if (read is Err) {
    // A name lookup falls back to the built-in security-level presets;
    // explicit paths and non-preset names stay loud.
    if (name != null) {
      final preset = CubePresets.maybeSpec(name: name, cwd: env.cwd);
      if (preset != null) return preset;
    }
    throw _notFound(filePath, name);
  }
  final content = (read as Ok<String, FileError>).value;
  final Object? document;
  try {
    document = loadYaml(content);
  } on YamlException catch (error) {
    throw ConfigException(
      'cube: invalid yaml in $filePath: ${error.message}',
    );
  }
  return CubeSpec.fromYaml(document, sourcePath: filePath);
}