npm package: @mikofia/xia-config-types
Description: TypeScript types for Mikofia Xia configuration files and custom rules
Author: mikofia
Latest version: 0.1.0

# @mikofia/xia-config-types

TypeScript type definitions for [Mikofia](https://github.com/mikofia/mikofia), a declarative, expressive file system linter.

## Installation

```bash
npm install --save-dev @mikofia/xia-config-types
```

or

```bash
pnpm add -D @mikofia/xia-config-types
```

or

```bash
yarn add -D @mikofia/xia-config-types
```

## Usage

### TypeScript Configuration Files

```typescript
// mikofia.config.ts
import type { Config } from '@mikofia/xia-config-types';

export default {
  ignore: ['node_modules', 'dist'],
  nodes: [
    {
      path: 'src',
      kind: 'directory',
      existence: 'required',
      children: [
        { path: 'index.ts', kind: 'file', existence: 'required' }
      ]
    }
  ]
} satisfies Config;
```

### JavaScript Configuration Files (with JSDoc)

```javascript
// mikofia.config.js
// @ts-check
/// <reference types="@mikofia/xia-config-types" />

/** @type {import('@mikofia/xia-config-types').Config} */
const config = {
  ignore: ['node_modules', 'dist'],
  nodes: [
    {
      path: 'src',
      kind: 'directory',
      existence: 'required',
      children: [
        { path: 'index.js', kind: 'file', existence: 'required' }
      ]
    }
  ]
};

export default config;
```

### Custom Rules

```typescript
// mikofia.config.ts
import type { Config, RuleFunction } from '@mikofia/xia-config-types';

const checkNamingConvention: RuleFunction = async (ctx) => {
  if (!ctx.name.match(/^[a-z0-9-]+$/)) {
    return {
      type: 'fail',
      violation: {
        key: 'invalid-naming',
        message: `Invalid name: ${ctx.name}. Use lowercase, numbers, and hyphens only.`
      }
    };
  }
  return { type: 'pass' };
};

const validatePackageJson: RuleFunction = async (ctx) => {
  if (ctx.name !== 'package.json') {
    return { type: 'skip', reason: 'Not a package.json file' };
  }

  const content = await ctx.fs.readJson(ctx.path);
  const pkg = content as Record<string, unknown>;

  if (!pkg.name || !pkg.version) {
    return {
      type: 'fail',
      violation: {
        key: 'missing-required-fields',
        message: "package.json must have 'name' and 'version' fields"
      }
    };
  }

  return { type: 'pass' };
};

export default {
  nodes: [
    {
      path: 'package.json',
      kind: 'file',
      existence: 'required',
      rules: [validatePackageJson]
    },
    {
      path: 'src',
      kind: 'directory',
      existence: 'required',
      rules: [checkNamingConvention]
    }
  ]
} satisfies Config;
```

## Type Definitions

### `Config`

The main configuration object for Mikofia.

```typescript
interface Config {
  ignore?: string[];
  nodes: Node[];
}
```

### `Node`

A node in the file structure tree, representing a file or directory.

```typescript
interface Node {
  path: string;
  existence?: Existence;
  kind?: NodeKind;
  children?: Node[];
  strict?: boolean | null;
  ignore?: string[];
  rules?: RuleFunction[];
}
```

### `Existence`

Specifies whether a file or directory must exist, may exist, or must not exist.

```typescript
type Existence = "required" | "optional" | "absent";
```

- `"required"`: The item must exist
- `"optional"`: The item may or may not exist (default)
- `"absent"`: The item must not exist

### `NodeKind`

Specifies the expected type of a filesystem item.

```typescript
type NodeKind = "file" | "directory" | "any";
```

- `"file"`: Must be a file
- `"directory"`: Must be a directory
- `"any"`: Can be either (default)

### `strict` Field Behavior

The `strict` field controls whether a directory allows only explicitly listed children.

```typescript
strict?: boolean | null;
```

- `true`: Strict mode enabled - only listed children are allowed
- `false`: Strict mode disabled - unlisted files/directories are allowed
- `null` or `undefined`: **Automatically defaults to `true` if `children` are defined, `false` otherwise**

**Important:** If you define `children` for a directory, strict mode will be automatically enabled unless you explicitly set `strict: false`.

**Example:**

```typescript
{
  path: 'src',
  kind: 'directory',
  children: [
    { path: 'index.ts', kind: 'file' }
  ]
  // strict is implicitly true - only index.ts is allowed in src/
}

{
  path: 'src',
  kind: 'directory',
  strict: false,  // explicitly disable strict mode
  children: [
    { path: 'index.ts', kind: 'file' }
  ]
  // a file named index.ts is allowed, but other files are also allowed
}
```

### `RuleFunction`

Custom validation rule function.

```typescript
type RuleFunction = (ctx: EvaluationContext) => RuleResult | Promise<RuleResult>;
```

### `EvaluationContext`

Context provided to custom validation rules.

```typescript
interface EvaluationContext {
  path: string;
  name: string;
  extension?: string;
  parent?: ParentInfo;
  siblings: SiblingInfo[];
  fs: {
    readFile(path: string): Promise<string>;
    readJson(path: string): Promise<unknown>;
    exists(path: string): boolean;
  };
}
```

### `RuleResult`

Result of a validation rule check.

```typescript
type RuleResult =
  | { type: "pass" }
  | { type: "fail"; violation: { key: string; message: string; path?: string } }
  | { type: "skip"; reason: string };
```

**Violation Fields:**

- `key`: Unique identifier for the violation type
- `message`: Human-readable error message
- `path` (optional): Custom path to report the violation at. If not specified, the path from the evaluation context will be used.

**Example with custom path:**

```typescript
const validateImports: RuleFunction = async (ctx) => {
  const content = await ctx.fs.readFile(ctx.path);
  const match = content.match(/import .+ from ['"](.+)['"]/);

  if (match && match[1].startsWith('../../../')) {
    return {
      type: 'fail',
      violation: {
        key: 'deep-import',
        message: 'Avoid imports with more than 2 parent directory references',
        path: ctx.path  // Explicitly specify which file has the violation
      }
    };
  }

  return { type: 'pass' };
};
```

## License

MIT

## Related

- [Mikofia](https://github.com/mikofia/mikofia) - Declarative, Expressive file system linter